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 : //
24 : // Capella 2000 import filter
25 : //
26 : #include "capella.h"
27 :
28 : #include <QFile>
29 : #include <QtMath>
30 :
31 : #include "engraving/dom/arpeggio.h"
32 : #include "engraving/dom/articulation.h"
33 : #include "engraving/dom/box.h"
34 : #include "engraving/dom/breath.h"
35 : #include "engraving/dom/chord.h"
36 : #include "engraving/dom/clef.h"
37 : #include "engraving/dom/dynamic.h"
38 : #include "engraving/dom/factory.h"
39 : #include "engraving/dom/hairpin.h"
40 : #include "engraving/dom/harmony.h"
41 : #include "engraving/dom/keysig.h"
42 : #include "engraving/dom/layoutbreak.h"
43 : #include "engraving/dom/lyrics.h"
44 : #include "engraving/dom/masterscore.h"
45 : #include "engraving/dom/measure.h"
46 : #include "engraving/dom/mscore.h"
47 : #include "engraving/dom/note.h"
48 : #include "engraving/dom/part.h"
49 : #include "engraving/dom/pitchspelling.h"
50 : #include "engraving/dom/rest.h"
51 : #include "engraving/dom/segment.h"
52 : #include "engraving/dom/sig.h"
53 : #include "engraving/dom/slur.h"
54 : #include "engraving/dom/staff.h"
55 : #include "engraving/dom/stafftext.h"
56 : #include "engraving/dom/text.h"
57 : #include "engraving/dom/tie.h"
58 : #include "engraving/dom/timesig.h"
59 : #include "engraving/dom/trill.h"
60 : #include "engraving/dom/tuplet.h"
61 : #include "engraving/dom/utils.h"
62 : #include "engraving/dom/volta.h"
63 :
64 : #include "engraving/editing/editstaffbrackets.h"
65 : #include "engraving/editing/transpose.h"
66 :
67 : #include "engraving/engravingerrors.h"
68 : #include "engraving/infrastructure/messagebox.h"
69 :
70 : #include "log.h"
71 :
72 : #include "translation.h"
73 :
74 : extern QString rtf2html(const QString&);
75 :
76 : using namespace mu::engraving;
77 :
78 : namespace mu::iex::capella {
79 : //---------------------------------------------------------
80 : // errmsg
81 : //---------------------------------------------------------
82 :
83 : const char* Capella::errmsg[] = {
84 : "no error",
85 : "bad file signature, no Capella file or not from version 2000 (3.0) or later?",
86 : "unexpected end of file",
87 : "bad voice signature",
88 : "bad staff signature",
89 : "bad system signature",
90 : "bad file content",
91 : };
92 :
93 : //---------------------------------------------------------
94 : // addDynamic
95 : //---------------------------------------------------------
96 :
97 0 : static void addDynamic(Score*, Segment* s, int track, const char* name)
98 : {
99 0 : Dynamic* d = Factory::createDynamic(s);
100 0 : d->setDynamicType(String::fromUtf8(name));
101 0 : d->setTrack(track);
102 0 : s->add(d);
103 0 : }
104 :
105 : //---------------------------------------------------------
106 : // addArticulationText
107 : //---------------------------------------------------------
108 :
109 0 : static void addArticulationText(Score*, ChordRest* cr, int track, SymId symId)
110 : {
111 0 : Articulation* na = Factory::createArticulation(cr);
112 0 : na->setTrack(track);
113 0 : na->setSymId(symId);
114 0 : cr->add(na);
115 0 : }
116 :
117 : //---------------------------------------------------------
118 : // SetCapGraceDuration
119 : //---------------------------------------------------------
120 :
121 0 : static void SetCapGraceDuration(Chord* chord, ChordObj* o)
122 : {
123 0 : NoteType nt = NoteType::APPOGGIATURA;
124 0 : if (o->nTremoloBars > 0) {
125 0 : nt = NoteType::ACCIACCATURA;
126 : }
127 0 : ((Chord*)chord)->setNoteType(nt);
128 0 : if (o->t == TIMESTEP::D4) {
129 0 : ((Chord*)chord)->setNoteType(NoteType::GRACE4);
130 0 : chord->setDurationType(DurationType::V_QUARTER);
131 0 : } else if (o->t == TIMESTEP::D_BREVE) {
132 0 : ((Chord*)chord)->setDurationType(DurationType::V_BREVE);
133 0 : } else if (o->t == TIMESTEP::D1) {
134 0 : ((Chord*)chord)->setDurationType(DurationType::V_WHOLE);
135 0 : } else if (o->t == TIMESTEP::D2) {
136 0 : ((Chord*)chord)->setDurationType(DurationType::V_HALF);
137 0 : } else if (o->t == TIMESTEP::D16) {
138 0 : ((Chord*)chord)->setNoteType(NoteType::GRACE16);
139 0 : chord->setDurationType(DurationType::V_16TH);
140 0 : } else if (o->t == TIMESTEP::D32) {
141 0 : ((Chord*)chord)->setNoteType(NoteType::GRACE32);
142 0 : chord->setDurationType(DurationType::V_32ND);
143 0 : } else if (o->t == TIMESTEP::D64) {
144 0 : ((Chord*)chord)->setDurationType(DurationType::V_64TH);
145 0 : } else if (o->t == TIMESTEP::D128) {
146 0 : ((Chord*)chord)->setDurationType(DurationType::V_128TH);
147 0 : } else if (o->t == TIMESTEP::D256) {
148 0 : ((Chord*)chord)->setDurationType(DurationType::V_256TH);
149 : } else {
150 0 : ((Chord*)chord)->setDurationType(DurationType::V_EIGHTH);
151 : }
152 0 : }
153 :
154 : //---------------------------------------------------------
155 : // processBasicDrawObj
156 : //---------------------------------------------------------
157 :
158 938 : static void processBasicDrawObj(QList<BasicDrawObj*> objects, Segment* s, int track, ChordRest* cr)
159 : {
160 938 : Score* score = s->score();
161 964 : for (BasicDrawObj* oo : objects) {
162 26 : switch (oo->type) {
163 6 : case CapellaType::SIMPLE_TEXT:
164 : {
165 6 : SimpleTextObj* st = static_cast<SimpleTextObj*>(oo);
166 6 : if (st->font().family() == "capella3") {
167 0 : QString text(st->text());
168 0 : if (text.size() == 1) {
169 0 : QChar c(text[0]);
170 0 : ushort code = c.unicode();
171 0 : switch (code) {
172 0 : case 'p':
173 0 : addDynamic(score, s, track, "p");
174 0 : break;
175 0 : case 'q':
176 0 : addDynamic(score, s, track, "pp");
177 0 : break;
178 0 : case 'r':
179 0 : addDynamic(score, s, track, "ppp");
180 0 : break;
181 0 : case 's':
182 0 : addDynamic(score, s, track, "sf");
183 0 : break;
184 0 : case 'f':
185 0 : addDynamic(score, s, track, "f");
186 0 : break;
187 0 : case 'g':
188 0 : addDynamic(score, s, track, "ff");
189 0 : break;
190 0 : case 'h':
191 0 : addDynamic(score, s, track, "fff");
192 0 : break;
193 0 : case 'i':
194 0 : addDynamic(score, s, track, "mp");
195 0 : break;
196 0 : case 'j':
197 0 : addDynamic(score, s, track, "mf");
198 0 : break;
199 0 : case 'z': // sfz
200 0 : addDynamic(score, s, track, "sfz");
201 0 : break;
202 0 : case '{':
203 0 : addDynamic(score, s, track, "fz");
204 0 : break;
205 0 : case '|':
206 0 : addDynamic(score, s, track, "fp");
207 0 : break;
208 0 : case 212: // dynamic m
209 0 : addDynamic(score, s, track, "m");
210 0 : break;
211 0 : case 213: // dynamic r
212 0 : addDynamic(score, s, track, "r");
213 0 : break;
214 0 : case 214: // dynamic s
215 0 : addDynamic(score, s, track, "s");
216 0 : break;
217 0 : case 215: // dynamic z
218 0 : addDynamic(score, s, track, "z");
219 0 : break;
220 0 : case 'k': // fermata down
221 0 : addArticulationText(score, cr, track, SymId::fermataBelow);
222 0 : break;
223 0 : case 'u': // fermata up
224 0 : addArticulationText(score, cr, track, SymId::fermataAbove);
225 0 : break;
226 0 : case 'd': // da capo D.C.
227 : case 'e': // dal segno D.S.
228 : case 'n': // segno coda
229 : case 'o': // segno coda (smaller)
230 : case 'y': // segno
231 : case '$': // segno variation
232 : case 'a': // pedal Ped.
233 : case 'b': // pedal asterisk *
234 : case 'v': // 8va
235 : case 186: // 15ma
236 0 : LOGD("Import of Capella text articulation %x(%c) not yet implemented", code, code);
237 0 : break;
238 0 : case 181: // caesura
239 : {
240 0 : Segment* seg = s->measure()->getSegment(SegmentType::Breath, cr ? cr->endTick() : s->tick());
241 0 : Breath* b = Factory::createBreath(seg);
242 0 : b->setTrack(track);
243 0 : b->setSymId(SymId::caesura);
244 0 : seg->add(b);
245 : }
246 0 : break;
247 0 : default:
248 0 : break;
249 : }
250 0 : if (cr && cr->isChord()) {
251 0 : switch (code) {
252 0 : case 172: // arpeggio (short)
253 : case 173: // arpeggio (long)
254 : {
255 0 : Arpeggio* a = Factory::createArpeggio(toChord(cr));
256 0 : a->setArpeggioType(ArpeggioType::NORMAL);
257 0 : if (mu::engraving::toChord(cr)->arpeggio()) { // there can be only one
258 0 : delete a;
259 0 : a = 0;
260 : } else {
261 0 : cr->add(a);
262 : }
263 : }
264 0 : break;
265 0 : case 187: // arpeggio (wiggle line, arrow up)
266 : {
267 0 : Arpeggio* a = Factory::createArpeggio(toChord(cr));
268 0 : a->setArpeggioType(ArpeggioType::UP);
269 0 : if ((toChord(cr))->arpeggio()) { // there can be only one
270 0 : delete a;
271 0 : a = 0;
272 : } else {
273 0 : cr->add(a);
274 : }
275 : }
276 0 : break;
277 0 : case 188: // arpeggio (wiggle line, arrow down)
278 : {
279 0 : Arpeggio* a = Factory::createArpeggio(toChord(cr));
280 0 : a->setArpeggioType(ArpeggioType::DOWN);
281 0 : if ((toChord(cr))->arpeggio()) { // there can be only one
282 0 : delete a;
283 0 : a = 0;
284 : } else {
285 0 : cr->add(a);
286 : }
287 : }
288 0 : break;
289 0 : default:
290 0 : break;
291 : }
292 : }
293 0 : break;
294 : }
295 0 : }
296 6 : StaffText* text = Factory::createStaffText(s);
297 12 : QFont f(st->font());
298 6 : text->setFamily(f.family());
299 6 : text->setItalic(f.italic());
300 : // text->setUnderline(f.underline());
301 : // text->setStrike(f.strikeOut());
302 6 : text->setBold(f.bold());
303 6 : text->setSize(f.pointSizeF());
304 :
305 6 : text->setPlainText(st->text());
306 6 : QPointF p(st->pos());
307 6 : p = p / 32.0 * score->style().spatium();
308 : // text->setUserOff(st->pos());
309 6 : text->setOffset(muse::PointF::fromQPointF(p));
310 : // LOGD("setText %s (%f %f)(%f %f) <%s>",
311 : // qPrintable(st->font().family()),
312 : // st->pos().x(), st->pos().y(), p.x(), p.y(), qPrintable(st->text()));
313 : AlignH textalign;
314 6 : switch (st->textalign()) {
315 0 : default:
316 : case 0:
317 0 : textalign = AlignH::LEFT;
318 0 : break;
319 6 : case 1:
320 6 : textalign = AlignH::HCENTER;
321 6 : break;
322 0 : case 2:
323 0 : textalign = AlignH::RIGHT;
324 0 : break;
325 : }
326 6 : text->setAlign(Align(textalign, AlignV::BASELINE));
327 6 : text->setOffset(muse::PointF(0.0, 2.0));
328 6 : text->setTrack(track);
329 6 : s->add(text);
330 : }
331 6 : break;
332 0 : case CapellaType::TRANSPOSABLE:
333 : {
334 0 : TransposableObj* to = static_cast<TransposableObj*>(oo);
335 0 : QString str = "";
336 0 : for (BasicDrawObj* bdo : to->variants) {
337 0 : SimpleTextObj* st = static_cast<SimpleTextObj*>(bdo);
338 0 : if (st->font().family() == "capella3") {
339 0 : for (const QChar& ch : st->text()) {
340 0 : if (ch == 'Q') {
341 0 : str += "b";
342 0 : } else if (ch == 'S') {
343 0 : str += "#";
344 0 : } else if (ch == 'R') {
345 0 : str += "natural";
346 : } else {
347 0 : str += ch;
348 : }
349 0 : }
350 : } else {
351 0 : str += st->text();
352 : }
353 : }
354 0 : Harmony* harmony = Factory::createHarmony(s);
355 0 : harmony->setHarmony(str);
356 0 : harmony->setTrack(track);
357 0 : s->add(harmony);
358 0 : break;
359 0 : }
360 0 : case CapellaType::TEXT:
361 0 : LOGD("======================Text:");
362 0 : break;
363 20 : default:
364 20 : break;
365 : }
366 : }
367 938 : }
368 :
369 : //---------------------------------------------------------
370 : // TupletFractionCap
371 : //---------------------------------------------------------
372 :
373 290 : Fraction TupletFractionCap(int tupletNotesSpanned, bool tuplettrp, bool tupletprol)
374 : {
375 290 : int dd = 0;
376 290 : int nn = 0;
377 290 : qreal exponent = 0;
378 290 : qreal tupletDenominator = tupletNotesSpanned;
379 290 : Fraction f(3, 2);
380 :
381 290 : if ((tupletDenominator > 0) && (tupletDenominator <= 15)) {
382 290 : if (tuplettrp) {
383 110 : exponent = qFloor(qLn(tupletDenominator / 3.0) / qLn(2.0));
384 : } else {
385 180 : exponent = qFloor(qLn(tupletDenominator) / qLn(2.0));
386 : }
387 : } else {
388 0 : LOGD("Unknown tuplet, tupletDenominator = %d", tupletNotesSpanned);
389 0 : return f;
390 : }
391 290 : if (tupletprol) {
392 6 : exponent += 1.0;
393 : }
394 290 : if (exponent < 0.0) {
395 0 : exponent = 0.0;
396 : }
397 290 : nn = tupletNotesSpanned;
398 290 : dd = static_cast<int>(qPow(2.0, exponent));
399 290 : if (tuplettrp) {
400 110 : dd = dd * 3;
401 : }
402 : CAPELLA_TRACE("Tuplet Fraction: %d / %d", nn, dd);
403 290 : return Fraction(nn, dd);
404 : }
405 :
406 : //---------------------------------------------------------
407 : // findChordRests -- find begin and end ChordRest for BasicDrawObj o
408 : // return true on success (both begin and end found)
409 : //---------------------------------------------------------
410 :
411 6 : static bool findChordRests(BasicDrawObj const* const o, Score* score, const int track, const Fraction& tick,
412 : ChordRest*& cr1, ChordRest*& cr2, NoteObj* no, QList<NoteObj*> objects)
413 : {
414 6 : cr1 = 0; // ChordRest where BasicDrawObj o begins
415 6 : cr2 = 0; // ChordRest where BasicDrawObj o ends
416 :
417 : // find the ChordRests where o begins and ends
418 6 : int n = o->nNotes + 1; // # notes in BasicDrawObj (nNotes is # notes following the first note)
419 6 : int graceNumber = 0;
420 6 : int graceNumber1 = 0;
421 6 : bool foundcr1 = false;
422 6 : Fraction tick2 = tick;
423 38 : for (NoteObj* nobj : objects) {
424 38 : BasicDurationalObj* d = 0;
425 38 : if (nobj->type() == CapellaNoteObjectType::REST) {
426 0 : d = static_cast<BasicDurationalObj*>(static_cast<RestObj*>(nobj));
427 0 : graceNumber = 0;
428 38 : } else if (nobj->type() == CapellaNoteObjectType::CHORD) {
429 25 : ChordObj* cho = static_cast<ChordObj*>(nobj);
430 25 : d = static_cast<BasicDurationalObj*>(cho);
431 25 : if (!(cho->invisible) && (cho->ticks().isZero())) { // grace note
432 0 : ++graceNumber;
433 : } else {
434 25 : graceNumber = 0;
435 : }
436 : }
437 38 : if (!d) {
438 13 : continue;
439 : }
440 25 : if (nobj == no) {
441 6 : foundcr1 = true;
442 6 : graceNumber1 = graceNumber;
443 : }
444 25 : Fraction ticks = Fraction(0, 1);
445 25 : if (foundcr1) {
446 15 : --n; // found the object corresponding to cr1, count down to find the second one
447 15 : ticks = d->ticks();
448 15 : if (d->tupletDenominator) {
449 0 : Fraction f = TupletFractionCap(d->tupletDenominator, d->tripartite, d->isProlonging);
450 0 : ticks = ticks / f;
451 : }
452 15 : if (nobj->type() == CapellaNoteObjectType::REST) {
453 0 : RestObj* ro = static_cast<RestObj*>(nobj);
454 0 : if (ro->fullMeasures) {
455 0 : Measure* m = score->undoGetMeasure(tick2);
456 0 : Fraction ft = m->ticks();
457 0 : ticks = ft * ro->fullMeasures;
458 : }
459 : }
460 15 : if (n == 0) {
461 6 : break;
462 : }
463 9 : tick2 += ticks;
464 : }
465 : }
466 : // Now we have the tick (tick) and the level of grace note (graceNumber1, if "no" is a grace note) for the first ChordRest
467 : // and the tick (tick2) and the level of grace note (graceNumber, if the target is a grace note) for the 2nd ChordRest
468 6 : for (Segment* seg = score->tick2segment(tick); seg; seg = seg->next1()) {
469 6 : if (seg->segmentType() != SegmentType::ChordRest) {
470 0 : continue;
471 : }
472 6 : ChordRest* cr = toChordRest(seg->element(track));
473 6 : if (cr) {
474 6 : if ((graceNumber1 > 0) && cr->isChord()) { // the spanner is starting from a grace note
475 0 : Chord* chord = toChord(cr);
476 0 : for (Chord* cc : chord->graceNotes()) {
477 0 : --graceNumber1;
478 0 : if ((graceNumber1 == 0) && (!cr1)) {
479 0 : cr1 = toChordRest(cc); // found first ChordRest
480 : }
481 : }
482 : }
483 6 : if (!cr1) {
484 6 : cr1 = cr; // found first ChordRest
485 : }
486 6 : break;
487 : }
488 : }
489 6 : for (Segment* seg = score->tick2segment(tick2); seg; seg = seg->next1()) {
490 6 : if (seg->segmentType() != SegmentType::ChordRest) {
491 0 : continue;
492 : }
493 6 : ChordRest* cr = toChordRest(seg->element(track));
494 6 : if (cr) {
495 6 : if ((graceNumber > 0) && cr->isChord()) { // the spanner is ending on a grace note
496 0 : Chord* chord = toChord(cr);
497 0 : for (Chord* cc : chord->graceNotes()) {
498 0 : --graceNumber;
499 0 : if ((graceNumber == 0) && (!cr2)) {
500 0 : cr2 = toChordRest(cc); // found 2nd ChordRest
501 : }
502 : }
503 : }
504 6 : if (!cr2) {
505 6 : cr2 = cr; // found 2nd ChordRest
506 : }
507 6 : break;
508 : }
509 : }
510 : CAPELLA_TRACE("findChordRests o %p nNotes %d score %p track %d tick %d cr1 %p cr2 %p",
511 : o, o->nNotes, score, track, tick.ticks(), cr1, cr2);
512 :
513 6 : if (!(cr1 && cr2)) {
514 0 : LOGD("first or second anchor for BasicDrawObj not found (tick %d type %d track %d first %p second %p)",
515 0 : tick.ticks(), int(o->type), track, cr1, cr2);
516 0 : return false;
517 : }
518 6 : return true;
519 : }
520 :
521 : //---------------------------------------------------------
522 : // createAndAddTimeSig
523 : //---------------------------------------------------------
524 :
525 5 : static Segment* createAndAddTimeSig(Score*, Measure* m, Fraction f, int track, Fraction tick)
526 : {
527 5 : auto s = m->getSegment(SegmentType::TimeSig, tick);
528 5 : TimeSig* ts = Factory::createTimeSig(s);
529 5 : ts->setSig(f);
530 5 : ts->setTrack(track);
531 5 : s->add(ts);
532 5 : return s;
533 : }
534 :
535 : //---------------------------------------------------------
536 : // readCapVoice
537 : //---------------------------------------------------------
538 :
539 98 : static Fraction readCapVoice(Score* score, CapVoice* cvoice, int staffIdx, const Fraction& t, bool capxMode)
540 : {
541 98 : Fraction tick(t);
542 98 : int voice = cvoice->voiceNo;
543 98 : int track = staffIdx * VOICES + voice;
544 :
545 : //
546 : // pass I
547 : //
548 98 : Fraction startTick = tick;
549 :
550 98 : Tuplet* tuplet = nullptr;
551 98 : int tupletNotesSpanned = 0; // Total number of notes/rests in the tuplet
552 98 : int tupletCurrentSequence = 0; // Current sequence number after adding to the tuplet (1 => first note/rest)
553 98 : bool tuplettrp = false;
554 98 : bool tupletprol = false;
555 98 : Fraction tupletTick = Fraction(0, 1);
556 98 : ClefType pclef = score->staff(staffIdx)->defaultClefType().concertClef;
557 :
558 98 : QList<Chord*> graceNotes;
559 1203 : for (NoteObj* no : cvoice->objects) {
560 1105 : switch (no->type()) {
561 3 : case CapellaNoteObjectType::REST:
562 : {
563 : CAPELLA_TRACE(" <Rest>");
564 3 : Measure* m = score->undoGetMeasure(tick);
565 3 : RestObj* o = static_cast<RestObj*>(no);
566 3 : Fraction ticks = o->ticks();
567 3 : if (o->invisible && ticks.isZero()) { // get rid of placeholders
568 0 : break;
569 : }
570 3 : TDuration d;
571 3 : d.setVal(ticks.ticks());
572 3 : if (o->tupletDenominator) {
573 3 : if (!tuplet) {
574 2 : tupletCurrentSequence = 0; // reset tuplet counter
575 2 : tupletNotesSpanned = (o->tupletCount) ? o->tupletCount + 1 : o->tupletDenominator;
576 2 : tuplettrp = o->tripartite;
577 2 : tupletprol = o->isProlonging;
578 2 : tupletTick = tick;
579 2 : tuplet = Factory::createTuplet(m);
580 2 : Fraction f = TupletFractionCap(o->tupletDenominator, tuplettrp, tupletprol);
581 2 : tuplet->setRatio(f);
582 2 : tuplet->setBaseLen(d);
583 2 : tuplet->setTrack(track);
584 2 : tuplet->setTick(tick);
585 2 : Fraction nn = ((o->tupletTicks.isZero()) ? (ticks * tupletNotesSpanned) : o->tupletTicks) / f;
586 2 : tuplet->setTicks(nn);
587 : }
588 : CAPELLA_TRACE("Tuplet(R) at %d: tupletDenominator: %d tri: %d prolonging: %d ticks %d objects %lld",
589 : tick.ticks(), o->tupletDenominator, o->tripartite, o->isProlonging, ticks.ticks(), o->objects.size());
590 : }
591 :
592 3 : Fraction ft = m->ticks();
593 3 : if (o->fullMeasures) {
594 0 : ticks = ft * o->fullMeasures;
595 0 : if (!o->invisible) {
596 0 : for (unsigned i = 0; i < o->fullMeasures; ++i) {
597 0 : Measure* m1 = score->undoGetMeasure(tick + (ft * i));
598 0 : Segment* s = m1->getSegment(SegmentType::ChordRest, tick + (ft * i));
599 0 : Rest* rest = Factory::createRest(s);
600 0 : rest->setDurationType(TDuration(DurationType::V_MEASURE));
601 0 : rest->setTicks(m1->ticks());
602 0 : rest->setTrack(staffIdx * VOICES + voice);
603 0 : s->add(rest);
604 : }
605 : }
606 : }
607 3 : if (!o->invisible || voice == 0) {
608 3 : Segment* s = m->getSegment(SegmentType::ChordRest, tick);
609 3 : Rest* rest = Factory::createRest(s);
610 3 : TDuration d1;
611 3 : if (o->fullMeasures) {
612 0 : d1.setType(DurationType::V_MEASURE);
613 0 : rest->setTicks(m->ticks());
614 : } else {
615 3 : d1.setVal(ticks.ticks());
616 3 : rest->setTicks(d1.fraction());
617 : }
618 3 : rest->setDurationType(d1);
619 3 : rest->setTrack(track);
620 3 : rest->setVisible(!o->invisible);
621 3 : s->add(rest);
622 3 : if (tuplet) {
623 3 : tuplet->add(rest);
624 3 : if (++tupletCurrentSequence >= tupletNotesSpanned) {
625 0 : o->tupletEnd = true; // mark the last position in the tuplet
626 : }
627 : }
628 3 : processBasicDrawObj(o->objects, s, track, rest);
629 : }
630 :
631 3 : if (tuplet) {
632 3 : if (o->tupletEnd) {
633 0 : tick = tuplet->endTick();
634 : //! NOTE If the tuplet is not added anywhere, then delete it
635 0 : if (tuplet->elements().empty()) {
636 0 : delete tuplet;
637 : }
638 :
639 0 : tuplet = nullptr;
640 : } else {
641 3 : tick += ticks / tuplet->ratio();
642 : }
643 : } else {
644 0 : tick += ticks;
645 : }
646 : }
647 3 : break;
648 935 : case CapellaNoteObjectType::CHORD:
649 : {
650 : CAPELLA_TRACE(" <Chord>");
651 935 : ChordObj* o = static_cast<ChordObj*>(no);
652 935 : Fraction ticks = o->ticks();
653 935 : if (o->invisible && ticks.isZero()) { // get rid of placeholders
654 0 : break;
655 : }
656 935 : TDuration d;
657 935 : d.setVal(ticks.ticks());
658 935 : Measure* m = score->undoGetMeasure(tick);
659 :
660 935 : bool isgracenote = (!(o->invisible) && (ticks.isZero()));
661 935 : if (o->tupletDenominator) {
662 253 : if (tuplet == nullptr) {
663 32 : tupletCurrentSequence = 0; // reset tuplet counter
664 32 : tupletNotesSpanned = (o->tupletCount) ? o->tupletCount + 1 : o->tupletDenominator;
665 32 : tuplettrp = o->tripartite;
666 32 : tupletprol = o->isProlonging;
667 32 : tupletTick = tick;
668 32 : tuplet = Factory::createTuplet(m);
669 32 : Fraction f = TupletFractionCap(o->tupletDenominator, tuplettrp, tupletprol);
670 32 : tuplet->setRatio(f);
671 32 : tuplet->setBaseLen(d);
672 32 : tuplet->setTrack(track);
673 32 : tuplet->setTick(tick);
674 32 : Fraction nn = ((o->tupletTicks.isZero()) ? (ticks * tupletNotesSpanned) : o->tupletTicks) / f;
675 32 : tuplet->setTicks(nn);
676 : }
677 : CAPELLA_TRACE("Tuplet(C) at %d: tupletDenominator: %d tri: %d prolonging: %d ticks %d objects %lld",
678 : tick.ticks(), o->tupletDenominator, o->tripartite, o->isProlonging, ticks.ticks(), o->objects.size());
679 : }
680 :
681 935 : Chord* chord = Factory::createChord(score->dummy());
682 935 : if (isgracenote) { // grace notes
683 0 : SetCapGraceDuration(chord, o);
684 0 : chord->setTicks(chord->durationType().fraction());
685 : } else { // normal notes
686 935 : chord->setDurationType(d);
687 935 : chord->setTicks(d.fraction());
688 : }
689 935 : chord->setTrack(track);
690 935 : switch (o->stemDir) {
691 0 : case ChordObj::StemDir::DOWN:
692 0 : chord->setStemDirection(DirectionV::DOWN);
693 0 : break;
694 0 : case ChordObj::StemDir::UP:
695 0 : chord->setStemDirection(DirectionV::UP);
696 0 : break;
697 0 : case ChordObj::StemDir::NONE:
698 0 : chord->setNoStem(true);
699 0 : break;
700 935 : case ChordObj::StemDir::AUTO:
701 : default:
702 935 : break;
703 : }
704 935 : Segment* s = m->getSegment(SegmentType::ChordRest, tick);
705 935 : if (isgracenote) {
706 0 : graceNotes.push_back(chord);
707 : } else {
708 935 : s->add(chord);
709 : // append grace notes before
710 935 : int ii = -1;
711 935 : for (ii = graceNotes.size() - 1; ii >= 0; ii--) {
712 0 : Chord* gc = graceNotes[ii];
713 0 : if (gc->voice() == chord->voice()) {
714 0 : chord->add(gc);
715 : }
716 : }
717 935 : graceNotes.clear();
718 : }
719 935 : if (tuplet) {
720 253 : tuplet->add(chord);
721 253 : if (++tupletCurrentSequence >= tupletNotesSpanned) {
722 34 : o->tupletEnd = true; // mark the last chord in the tuplet
723 : }
724 : }
725 935 : ClefType clef = score->staff(staffIdx)->clef(tick);
726 935 : Key key = score->staff(staffIdx)->key(tick);
727 : int off;
728 935 : switch (clef) {
729 888 : case ClefType::G: off = 0;
730 888 : break;
731 0 : case ClefType::G8_VA: off = 7;
732 0 : break;
733 0 : case ClefType::G15_MA: off = 14;
734 0 : break;
735 4 : case ClefType::G8_VB: off = -7;
736 4 : break;
737 43 : case ClefType::F: off = -14;
738 43 : break;
739 0 : case ClefType::F8_VB: off = -21;
740 0 : break;
741 0 : case ClefType::F15_MB: off = -28;
742 0 : break;
743 0 : case ClefType::F_B: off = -14;
744 0 : break;
745 0 : case ClefType::F_C: off = -14;
746 0 : break;
747 0 : case ClefType::C1: off = -7;
748 0 : break;
749 0 : case ClefType::C2: off = -7;
750 0 : break;
751 0 : case ClefType::C3: off = -7;
752 0 : break;
753 0 : case ClefType::C4: off = -7;
754 0 : break;
755 0 : case ClefType::C4_8VB: off = -14;
756 0 : break;
757 0 : case ClefType::C5: off = -7;
758 0 : break;
759 0 : case ClefType::G_1: off = 0;
760 0 : break;
761 0 : case ClefType::F_8VA: off = -7;
762 0 : break;
763 0 : case ClefType::F_15MA: off = 0;
764 0 : break;
765 0 : default: off = 0;
766 0 : LOGD("clefType %d not implemented", int(clef));
767 : }
768 : // LOGD("clef %hhd off %d", clef, off);
769 :
770 : static std::array<int, 15> keyOffsets = {
771 : /* -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 */
772 : /* */ 7, 4, 1, 5, 2, 6, 3, 0, 4, 1, 5, 2, 6, 3, 0
773 : };
774 1870 : if (int(key) + 7 >= int(keyOffsets.size())) {
775 0 : throw Capella::Error::BAD_FORMAT;
776 : }
777 935 : off += keyOffsets[int(key) + 7];
778 :
779 1870 : for (const CNote& n : o->notes) {
780 935 : Note* note = Factory::createNote(chord);
781 935 : int pitch = 0;
782 : // .cap import: pitch contains the diatonic note number relative to clef and key
783 : // .capx import: pitch the MIDI note number instead
784 935 : if (capxMode) {
785 363 : pitch = n.pitch;
786 : } else {
787 572 : int l = n.pitch + off + 7 * 6;
788 572 : int octave = 0;
789 572 : while (l < 0) {
790 0 : l += 7;
791 0 : octave--;
792 : }
793 572 : octave += l / 7;
794 572 : l = l % 7;
795 :
796 572 : pitch = pitchKeyAdjust(l, key) + octave * 12;
797 : }
798 935 : pitch += n.alteration;
799 935 : pitch += score->staff(staffIdx)->part()->instrument()->transpose().chromatic; // assume not in concert pitch
800 :
801 935 : chord->add(note);
802 935 : note->setPitch(clampPitch(pitch));
803 935 : note->setHeadGroup(NoteHeadGroup(n.headGroup));
804 : // TODO: compute tpc from pitch & line
805 935 : note->setTpcFromPitch();
806 935 : if (o->rightTie) {
807 1 : Tie* tie = Factory::createTie(note);
808 1 : tie->setStartNote(note);
809 1 : tie->setTrack(track);
810 1 : note->setTieFor(tie);
811 : }
812 : }
813 941 : for (Verse v : o->verse) {
814 6 : Lyrics* l = Factory::createLyrics(chord);
815 6 : l->setTrack(track);
816 6 : l->setPlainText(v.text);
817 6 : if (v.hyphen) {
818 0 : l->setSyllabic(LyricsSyllabic::BEGIN);
819 : }
820 6 : l->setVerse(v.num);
821 6 : l->initTextStyleType(l->isEven() ? TextStyleType::LYRICS_EVEN : TextStyleType::LYRICS_ODD, /*preserveDifferent*/ true);
822 6 : chord->add(l);
823 6 : }
824 :
825 935 : processBasicDrawObj(o->objects, s, track, chord);
826 935 : switch (o->articulation) {
827 : case 7: // "weak beat"
828 : case 8: // "strong beat"
829 935 : default: if (o->articulation) {
830 0 : LOGD("Articulation # %d not implemented", o->articulation);
831 : }
832 935 : break;
833 : }
834 :
835 935 : if (tuplet) {
836 253 : if (o->tupletEnd) {
837 34 : tick = tuplet->endTick();
838 : //! NOTE If the tuplet is not added anywhere, then delete it
839 34 : if (tuplet->elements().empty()) {
840 0 : delete tuplet;
841 : }
842 :
843 34 : tuplet = nullptr;
844 : } else {
845 219 : tick += ticks / tuplet->ratio();
846 : }
847 : } else {
848 682 : tick += ticks;
849 : }
850 : }
851 935 : break;
852 88 : case CapellaNoteObjectType::CLEF:
853 : {
854 : CAPELLA_TRACE(" <Clef>");
855 88 : CapClef* o = static_cast<CapClef*>(no);
856 88 : ClefType nclef = o->clef();
857 : CAPELLA_TRACE("%d:%d <Clef> %s line %d oct %d clef %d",
858 : tick.ticks(), staffIdx, o->name(), int(o->line), int(o->oct), int(o->clef()));
859 88 : if (nclef == ClefType::INVALID || nclef == pclef) {
860 : break;
861 : }
862 6 : pclef = nclef;
863 : // staff(staffIdx)->setClef(tick, nclef);
864 : Segment* s;
865 6 : Measure* m = score->undoGetMeasure(tick);
866 6 : if (tick == m->tick()) {
867 6 : s = m->getSegment(SegmentType::HeaderClef, tick);
868 : } else {
869 0 : s = m->getSegment(SegmentType::Clef, tick);
870 : }
871 6 : Clef* clef = Factory::createClef(s);
872 6 : clef->setClefType(nclef);
873 6 : clef->setTrack(staffIdx * VOICES);
874 6 : s->add(clef);
875 : }
876 6 : break;
877 47 : case CapellaNoteObjectType::KEY:
878 : {
879 : CAPELLA_TRACE(" <Key>");
880 47 : CapKey* o = static_cast<CapKey*>(no);
881 47 : KeySigEvent key = score->staff(staffIdx)->keySigEvent(tick);
882 47 : KeySigEvent okey = key;
883 47 : Key tKey = Key(o->signature);
884 47 : Key cKey = tKey;
885 47 : Interval v = score->staff(staffIdx)->part()->instrument(tick)->transpose();
886 47 : if (!v.isZero() && !score->style().styleB(mu::engraving::Sid::concertPitch)) {
887 0 : cKey = Transpose::transposeKey(tKey, v);
888 : // if there are more than 6 accidentals in transposing key, it cannot be PreferSharpFlat::AUTO
889 0 : Part* part = score->staff(staffIdx)->part();
890 0 : if ((tKey > 6 || tKey < -6) && part->preferSharpFlat() == PreferSharpFlat::AUTO) {
891 0 : part->setPreferSharpFlat(PreferSharpFlat::NONE);
892 : }
893 : }
894 47 : okey.setConcertKey(cKey);
895 47 : okey.setKey(tKey);
896 47 : if (!(key == okey)) {
897 40 : score->staff(staffIdx)->setKey(tick, okey);
898 40 : Measure* m = score->undoGetMeasure(tick);
899 40 : Segment* s = m->getSegment(SegmentType::KeySig, tick);
900 40 : KeySig* ks = Factory::createKeySig(s);
901 40 : ks->setTrack(staffIdx * VOICES);
902 40 : ks->setKeySigEvent(okey);
903 40 : s->add(ks);
904 : }
905 47 : }
906 47 : break;
907 27 : case CapellaNoteObjectType::METER:
908 : {
909 27 : CapMeter* o = static_cast<CapMeter*>(no);
910 : CAPELLA_TRACE(" <Meter> tick %d %d/%d", tick.ticks(), o->numerator, 1 << o->log2Denom);
911 27 : if (o->log2Denom > 7 || o->log2Denom < 0) {
912 0 : ASSERT_X("illegal fraction");
913 : }
914 27 : SigEvent se = score->sigmap()->timesig(tick);
915 27 : Fraction f(o->numerator, 1 << o->log2Denom);
916 27 : SigEvent ne(f);
917 27 : if (!(se == ne)) {
918 5 : score->sigmap()->add(tick.ticks(), ne);
919 : }
920 :
921 : // do not add timesig again
922 27 : Measure* m = score->undoGetMeasure(tick);
923 27 : Segment* s = m->findSegment(SegmentType::TimeSig, tick);
924 27 : if (s) {
925 23 : EngravingItem* e = s->element(trackZeroVoice(track));
926 23 : if (e && toTimeSig(e)->sig() == f) {
927 22 : break;
928 : }
929 : }
930 : // create timesig in current track
931 5 : s = createAndAddTimeSig(score, m, f, track, tick);
932 : // if not present, also create timesig in track 0
933 : // to prevent corrupt .msc[xz] files when first staff
934 : // is empty and timesig is not 4/4
935 5 : if (!(s->element(0))) {
936 0 : createAndAddTimeSig(score, m, f, 0, tick);
937 : }
938 5 : m->setTicks(f);
939 : }
940 5 : break;
941 5 : case CapellaNoteObjectType::EXPL_BARLINE:
942 : case CapellaNoteObjectType::IMPL_BARLINE: // does not exist?
943 : {
944 5 : CapExplicitBarline* o = static_cast<CapExplicitBarline*>(no);
945 : CAPELLA_TRACE(" <Barline>");
946 5 : Measure* pm = 0; // the previous measure (the one terminated by this barline)
947 5 : if (tick > Fraction(0, 1)) {
948 5 : pm = score->undoGetMeasure(tick - Fraction::fromTicks(1));
949 : }
950 5 : if (pm) {
951 5 : Fraction ticks = tick - pm->tick();
952 5 : if ((ticks > Fraction(0, 1)) && ticks != pm->ticks()) {
953 : // this is a measure with different actual duration
954 1 : Fraction f = ticks;
955 1 : pm->setTicks(f);
956 : }
957 : }
958 :
959 5 : BarLineType st = o->type();
960 5 : if (st & BarLineType::NORMAL) {
961 3 : break;
962 : }
963 :
964 2 : if (st & BarLineType::START_REPEAT || st & BarLineType::END_START_REPEAT) {
965 0 : Measure* nm = 0; // the next measure (the one started by this barline)
966 0 : nm = score->undoGetMeasure(tick);
967 0 : if (nm) {
968 0 : nm->setRepeatStart(true);
969 : }
970 : }
971 :
972 2 : if (st & BarLineType::END_REPEAT || st & BarLineType::END_START_REPEAT) {
973 1 : if (pm) {
974 1 : pm->setRepeatEnd(true);
975 : }
976 : }
977 : }
978 2 : break;
979 0 : case CapellaNoteObjectType::PAGE_BKGR:
980 : CAPELLA_TRACE(" <PageBreak>");
981 0 : break;
982 : }
983 : }
984 98 : Fraction endTick = tick;
985 :
986 : //
987 : // pass II
988 : //
989 98 : tick = startTick;
990 1203 : for (NoteObj* no : cvoice->objects) {
991 1105 : BasicDurationalObj* d = 0;
992 1105 : if (no->type() == CapellaNoteObjectType::REST) {
993 3 : d = static_cast<BasicDurationalObj*>(static_cast<RestObj*>(no));
994 1102 : } else if (no->type() == CapellaNoteObjectType::CHORD) {
995 935 : d = static_cast<BasicDurationalObj*>(static_cast<ChordObj*>(no));
996 : }
997 1105 : if (!d) {
998 167 : continue;
999 : }
1000 964 : for (BasicDrawObj* o : d->objects) {
1001 26 : switch (o->type) {
1002 6 : case CapellaType::SIMPLE_TEXT:
1003 : // LOGD("simple text at %d", tick);
1004 6 : break;
1005 0 : case CapellaType::WAVY_LINE:
1006 0 : break;
1007 4 : case CapellaType::SLUR:
1008 : {
1009 : // SlurObj* so = static_cast<SlurObj*>(o);
1010 : // LOGD("slur tick %d %d-%d-%d-%d %d-%d", tick, so->nEnd, so->nMid,
1011 : // so->nDotDist, so->nDotWidth, so->nRefNote, so->nNotes);
1012 4 : ChordRest* cr1 = 0; // ChordRest where slur begins
1013 4 : ChordRest* cr2 = 0; // ChordRest where slur ends
1014 4 : bool res = findChordRests(o, score, track, tick, cr1, cr2, no, cvoice->objects);
1015 :
1016 4 : if (res) {
1017 4 : if (cr1 == cr2) {
1018 0 : LOGD("first and second anchor for slur identical (tick %d track %d first %p second %p)",
1019 : tick.ticks(), track, cr1, cr2);
1020 : } else {
1021 4 : Slur* slur = Factory::createSlur(score->dummy());
1022 : CAPELLA_TRACE("tick %d track %d cr1 %p cr2 %p -> slur %p",
1023 : tick.ticks(), track, cr1, cr2, slur);
1024 4 : slur->setTick(cr1->tick());
1025 4 : slur->setTick2(cr2->tick());
1026 4 : slur->setStartElement(cr1);
1027 4 : slur->setEndElement(cr2);
1028 4 : slur->setTrack(cr1->track());
1029 4 : slur->setTrack2(cr2->track());
1030 4 : score->addElement(slur);
1031 : }
1032 : }
1033 : }
1034 4 : break;
1035 0 : case CapellaType::TEXT: {
1036 0 : TextObj* to = static_cast<TextObj*>(o);
1037 0 : MeasureBase* measure = score->measures()->first();
1038 0 : Text* s = Factory::createText(measure, TextStyleType::TITLE);
1039 0 : QString ss = ::rtf2html(QString(to->text));
1040 :
1041 : // CAPELLA_TRACE("string %f:%f w %d ratio %d <%s>",
1042 : // to->relPos.x(), to->relPos.y(), to->width, to->yxRatio, qPrintable(ss));
1043 0 : s->setXmlText(ss);
1044 :
1045 0 : if (!measure->isVBox()) {
1046 0 : MeasureBase* mb = Factory::createVBox(score);
1047 0 : mb->setTick(Fraction(0, 1));
1048 0 : score->addMeasure(mb, measure);
1049 0 : measure = mb;
1050 : }
1051 0 : s->setOwnershipParent(measure);
1052 0 : measure->add(s);
1053 0 : }
1054 0 : break;
1055 2 : case CapellaType::VOLTA:
1056 : {
1057 2 : VoltaObj* vo = static_cast<VoltaObj*>(o);
1058 2 : ChordRest* cr1 = 0; // ChordRest where volta begins
1059 2 : ChordRest* cr2 = 0; // ChordRest where volta ends
1060 2 : bool res = findChordRests(o, score, track, tick, cr1, cr2, no, cvoice->objects);
1061 :
1062 2 : if (res) {
1063 2 : Volta* volta = Factory::createVolta(score->dummy());
1064 2 : volta->setTrack(track);
1065 2 : volta->setTrack2(track);
1066 : // TODO also support endings such as "1 - 3"
1067 4 : volta->setText(QString("%1.").arg(vo->to));
1068 2 : volta->endings().push_back(vo->to);
1069 2 : if (vo->bRight) {
1070 1 : volta->setVoltaType(Volta::Type::CLOSED);
1071 : } else {
1072 1 : volta->setVoltaType(Volta::Type::OPEN);
1073 : }
1074 2 : volta->setTick(cr1->measure()->tick());
1075 2 : volta->setTick2(cr2->measure()->endTick());
1076 2 : score->addElement(volta);
1077 : }
1078 : }
1079 2 : break;
1080 0 : case CapellaType::TRILL:
1081 : {
1082 0 : TrillObj* tro = static_cast<TrillObj*>(o);
1083 0 : ChordRest* cr1 = 0; // ChordRest where trill line begins
1084 0 : ChordRest* cr2 = 0; // ChordRest where trill line ends
1085 0 : bool res = findChordRests(o, score, track, tick, cr1, cr2, no, cvoice->objects);
1086 0 : if (res) {
1087 0 : if (cr1 == cr2) {
1088 0 : LOGD("first and second anchor for trill line identical (tick %d track %d first %p second %p)",
1089 : tick.ticks(), track, cr1, cr2);
1090 : } else {
1091 0 : Trill* trill = Factory::createTrill(score->dummy());
1092 0 : trill->setTrack(track);
1093 0 : trill->setTrack2(track);
1094 0 : trill->setTick(cr1->tick());
1095 0 : trill->setTick2(cr2->tick());
1096 0 : if (!(tro->trillSign)) {
1097 0 : trill->setTrillType(TrillType::PRALLPRALL_LINE);
1098 : }
1099 0 : score->addElement(trill);
1100 : }
1101 : }
1102 : }
1103 0 : break;
1104 0 : case CapellaType::WEDGE:
1105 : {
1106 0 : WedgeObj* wdgo = static_cast<WedgeObj*>(o);
1107 0 : ChordRest* cr1 = 0; // ChordRest where hairpin begins
1108 0 : ChordRest* cr2 = 0; // ChordRest where hairpin ends
1109 0 : bool res = findChordRests(o, score, track, tick, cr1, cr2, no, cvoice->objects);
1110 0 : if (res) {
1111 0 : if (cr1 == cr2) {
1112 0 : LOGD("first and second anchor for hairpin identical (tick %d track %d first %p second %p)",
1113 : tick.ticks(), track, cr1, cr2);
1114 : } else {
1115 0 : Hairpin* hp = Factory::createHairpin(score->dummy());
1116 0 : if (wdgo->decresc) {
1117 0 : hp->setHairpinType(HairpinType::DIM_HAIRPIN);
1118 : } else {
1119 0 : hp->setHairpinType(HairpinType::CRESC_HAIRPIN);
1120 : }
1121 0 : hp->setTick(cr1->tick());
1122 0 : hp->setTick2(cr2->tick());
1123 0 : hp->setTrack(track);
1124 0 : hp->setTrack2(track);
1125 0 : score->addSpanner(hp);
1126 : }
1127 : }
1128 : }
1129 0 : break;
1130 14 : default:
1131 14 : break;
1132 : }
1133 : }
1134 938 : Fraction ticks = d->ticks();
1135 938 : if (d->tupletDenominator) {
1136 256 : Fraction f = TupletFractionCap(d->tupletDenominator, d->tripartite, d->isProlonging);
1137 256 : ticks = ticks / f;
1138 : }
1139 938 : if (no->type() == CapellaNoteObjectType::REST) {
1140 3 : RestObj* o = static_cast<RestObj*>(no);
1141 3 : if (o->fullMeasures) {
1142 0 : Measure* m = score->undoGetMeasure(tick);
1143 0 : Fraction ft = m->ticks();
1144 0 : ticks = ft * o->fullMeasures;
1145 : }
1146 : }
1147 938 : tick += ticks;
1148 : }
1149 98 : return endTick;
1150 98 : }
1151 :
1152 : //---------------------------------------------------------
1153 : // needPart -- determine if a staff needs its own part
1154 : //---------------------------------------------------------
1155 :
1156 : // As Capella does not define parts (it only knows about staves,
1157 : // MIDI instruments numbers, brackets and braces), the following
1158 : // algorithm is used:
1159 : // - every staff is a separate part
1160 : // - unless:
1161 : // - it is in a brace
1162 : // - it is not the first staff in the brace
1163 : // - it has the same MIDI instrument as the previous staff
1164 : // Common cases:
1165 : // - Keyboards: two or three staves with the same MIDI instrument and a brace
1166 : // -> create one part
1167 : // - SATB: two or four staves with the same MIDI instrument and a bracket
1168 : // -> create two or four parts
1169 :
1170 34 : static bool needPart(const int prevInst, const int currInst, const int staffIdx, QList<CapBracket> const& bracketList)
1171 : {
1172 35 : for (CapBracket cb : bracketList) {
1173 1 : if (prevInst == currInst && cb.from < staffIdx && staffIdx <= cb.to && cb.curly) {
1174 0 : return false;
1175 : }
1176 : }
1177 34 : return true;
1178 : }
1179 :
1180 : //---------------------------------------------------------
1181 : // convertCapella
1182 : //---------------------------------------------------------
1183 :
1184 33 : void convertCapella(Score* score, Capella* cap, bool capxMode)
1185 : {
1186 33 : if (cap->systems.isEmpty()) {
1187 0 : return;
1188 : }
1189 :
1190 33 : score->style().set(Sid::measureSpacing, 1.0);
1191 33 : score->style().setSpatium(cap->normalLineDist * DPMM);
1192 33 : score->style().set(Sid::smallStaffMag, cap->smallLineDist / cap->normalLineDist);
1193 33 : score->style().set(Sid::minSystemDistance, 8_sp);
1194 33 : score->style().set(Sid::maxSystemDistance, 12_sp);
1195 :
1196 133 : for (CapSystem* csys : cap->systems) {
1197 : CAPELLA_TRACE("System:");
1198 210 : for (CapStaff* cstaff : csys->staves) {
1199 110 : CapStaffLayout* cl = cap->staffLayout(cstaff->iLayout);
1200 110 : if (!cl) {
1201 2 : throw Capella::Error::BAD_FORMAT;
1202 : }
1203 : CAPELLA_TRACE(" Staff layout <%s><%s><%s><%s><%s> %d barline %d-%d mode %d",
1204 : qPrintable(cl->descr), qPrintable(cl->name), qPrintable(cl->abbrev),
1205 : qPrintable(cl->intermediateName), qPrintable(cl->intermediateAbbrev),
1206 : cstaff->iLayout, cl->barlineFrom, cl->barlineTo, cl->barlineMode);
1207 : }
1208 : }
1209 :
1210 : //
1211 : // find out the maximum number of staves
1212 : //
1213 31 : int staves = 0;
1214 131 : for (CapSystem* csys : cap->systems) {
1215 100 : staves = qMax(staves, csys->staves.size());
1216 : }
1217 : //
1218 : // check the assumption that every stave should be
1219 : // associated with a CapStaffLayout
1220 : //
1221 31 : if (staves != cap->staffLayouts().size()) {
1222 4 : LOGD("Capella: max number of staves != number of staff layouts (%d, %lld)",
1223 2 : staves, cap->staffLayouts().size());
1224 2 : staves = qMax(staves, cap->staffLayouts().size());
1225 : }
1226 :
1227 : // set the initial time signature
1228 31 : CapStaff* cs = cap->systems[0]->staves[0];
1229 31 : if (cs->log2Denom <= 7) {
1230 31 : score->sigmap()->add(0, Fraction(cs->numerator, 1 << cs->log2Denom));
1231 : }
1232 :
1233 : // create parts and staves
1234 31 : Staff* bstaff = 0;
1235 31 : int span = 1;
1236 31 : int midiPatch = -1; // the previous MIDI patch (instrument)
1237 31 : Part* part = 0;
1238 65 : for (int staffIdx = 0; staffIdx < staves; ++staffIdx) {
1239 36 : CapStaffLayout* cl = cap->staffLayout(staffIdx);
1240 36 : if (!cl) {
1241 2 : throw Capella::Error::BAD_FORMAT;
1242 : }
1243 : // CAPELLA_TRACE("MIDI staff %d program %d", staffIdx, cl->sound);
1244 :
1245 : // create a new part if necessary
1246 34 : if (needPart(midiPatch, cl->sound, staffIdx, cap->brackets)) {
1247 34 : part = new Part(score);
1248 34 : score->appendPart(part);
1249 : }
1250 34 : midiPatch = cl->sound;
1251 :
1252 34 : Staff* s = Factory::createStaff(part);
1253 34 : s->initFromStaffType(0);
1254 :
1255 34 : if (cl->bPercussion) {
1256 0 : part->setMidiProgram(0, 128);
1257 : } else {
1258 34 : part->setMidiProgram(cl->sound, 0);
1259 : }
1260 34 : part->setPlainLongName(cl->name);
1261 34 : part->setPlainShortName(cl->abbrev);
1262 :
1263 : // ClefType clefType = CapClef::clefType(cl->form, cl->line, cl->oct);
1264 : // s->setClef(0, clefType);
1265 34 : s->setBarLineSpan(false);
1266 34 : if (bstaff == 0) {
1267 31 : bstaff = s;
1268 31 : span = 0;
1269 : }
1270 34 : ++span;
1271 34 : if (cl->barlineMode == 1) {
1272 16 : bstaff->setBarLineSpan(span != 0);
1273 16 : bstaff = 0;
1274 : }
1275 :
1276 34 : s->staffType(Fraction(0, 1))->setSmall(cl->bSmall);
1277 34 : Interval interval;
1278 : // guess diatonic transposition from chromatic transposition for the instrument
1279 34 : int values[23] = { -6, -6, -5, -5, -4, -3, -3, -2, -2, -1, -1, 0, 1, 1, 2, 2, 3, 4, 4, 5, 5, 6, 6 };
1280 34 : interval.diatonic = values[(cl->transp % 12) + 11] + (cl->transp / 12) * 7;
1281 34 : interval.chromatic = cl->transp;
1282 34 : s->part()->instrument()->setTranspose(interval);
1283 34 : score->appendStaff(s);
1284 : }
1285 29 : if (bstaff) {
1286 15 : bstaff->setBarLineSpan(span != 0);
1287 : }
1288 :
1289 30 : for (CapBracket cb : cap->brackets) {
1290 : CAPELLA_TRACE("Bracket %d-%d curly %d", cb.from, cb.to, cb.curly);
1291 1 : Staff* staff = muse::value(score->staves(), cb.from);
1292 1 : if (staff == 0) {
1293 0 : LOGD("bad bracket 'from' value");
1294 0 : continue;
1295 : }
1296 1 : EditStaffBrackets::setBracketType(score, staff->idx(), 0, cb.curly ? BracketType::BRACE : BracketType::NORMAL);
1297 1 : EditStaffBrackets::setBracketSpan(score, staff->idx(), 0, cb.to - cb.from + 1);
1298 : }
1299 29 : MeasureBase* measure = nullptr;
1300 29 : for (BasicDrawObj* o : cap->backgroundChord->objects) {
1301 0 : switch (o->type) {
1302 0 : case CapellaType::SIMPLE_TEXT:
1303 : {
1304 0 : SimpleTextObj* to = static_cast<SimpleTextObj*>(o);
1305 : TextStyleType tid;
1306 0 : switch (to->textalign()) {
1307 0 : case 0: tid = TextStyleType::LYRICIST;
1308 0 : break;
1309 0 : case 1: tid = TextStyleType::TITLE;
1310 0 : break;
1311 0 : case 2: tid = TextStyleType::COMPOSER;
1312 0 : break;
1313 0 : default: tid = TextStyleType::DEFAULT;
1314 0 : break;
1315 : }
1316 :
1317 0 : if (!measure) {
1318 0 : measure = Factory::createTitleVBox(score);
1319 0 : score->addMeasure(measure, score->measures()->first());
1320 : }
1321 :
1322 0 : Text* s = Factory::createText(measure, tid);
1323 0 : QFont f(to->font());
1324 0 : s->setItalic(f.italic());
1325 : // s->setUnderline(f.underline());
1326 : // s->setStrike(f.strikeOut());
1327 0 : s->setBold(f.bold());
1328 0 : s->setSize(f.pointSizeF());
1329 :
1330 0 : QString ss = to->text();
1331 0 : s->setPlainText(ss);
1332 :
1333 0 : measure->add(s);
1334 : // LOGD("page background object type %d (CapellaType::SIMPLE_TEXT) text %s", o->type, qPrintable(ss));
1335 : }
1336 0 : break;
1337 0 : default:
1338 0 : LOGD("page background object type %d", int(o->type));
1339 0 : break;
1340 : }
1341 : }
1342 :
1343 29 : if (cap->topDist) {
1344 28 : VBox* mb = 0;
1345 28 : MeasureBaseList* mbl = score->measures();
1346 28 : if (mbl->size() && mbl->first()->isVBox()) {
1347 0 : mb = static_cast<VBox*>(mbl->first());
1348 : } else {
1349 28 : VBox* vb = Factory::createTitleVBox(score);
1350 28 : score->addMeasure(vb, mb);
1351 28 : mb = vb;
1352 : }
1353 28 : mb->setBoxHeight(Spatium(cap->topDist));
1354 : }
1355 :
1356 29 : Fraction systemTick = Fraction(0, 1);
1357 123 : for (CapSystem* csys : cap->systems) {
1358 : CAPELLA_TRACE("readCapSystem");
1359 : /*
1360 : if (csys->explLeftIndent > 0) {
1361 : HBox* mb = Factory::createHBox(score);
1362 : mb->setTick(systemTick);
1363 : mb->setBoxWidth(Spatium(csys->explLeftIndent));
1364 : score->addMeasure(mb);
1365 : }
1366 : */
1367 94 : Fraction mtick = Fraction(0, 1);
1368 194 : for (CapStaff* cstaff : csys->staves) {
1369 : //
1370 : // assumption: layout index is mscore staffIdx
1371 : // which means that there is a 1:1 relation between layout/staff
1372 : //
1373 :
1374 : CAPELLA_TRACE(" ReadCapStaff %d/%d", cstaff->numerator, 1 << cstaff->log2Denom);
1375 100 : int staffIdx = cstaff->iLayout;
1376 100 : if (!score->staff(staffIdx)) {
1377 0 : continue;
1378 : }
1379 198 : for (CapVoice* cvoice : cstaff->voices) {
1380 98 : Fraction tick = readCapVoice(score, cvoice, staffIdx, systemTick, capxMode);
1381 98 : if (tick > mtick) {
1382 94 : mtick = tick;
1383 : }
1384 : }
1385 : }
1386 94 : Measure* m = score->tick2measure(mtick - Fraction::fromTicks(1));
1387 94 : if (m && !m->lineBreak()) {
1388 84 : LayoutBreak* lb = Factory::createLayoutBreak(m);
1389 84 : lb->setLayoutBreakType(LayoutBreakType::LINE);
1390 84 : lb->setTrack(0);
1391 84 : m->add(lb);
1392 : }
1393 94 : systemTick = mtick;
1394 : }
1395 :
1396 : //
1397 : // fill empty measures with rests
1398 : //
1399 29 : SegmentType st = SegmentType::ChordRest;
1400 185 : for (Measure* m = score->firstMeasure(); m; m = m->nextMeasure()) {
1401 318 : for (size_t staffIdx = 0; staffIdx < score->staves().size(); ++staffIdx) {
1402 162 : bool empty = true;
1403 162 : for (Segment* s = m->first(st); s; s = s->next(st)) {
1404 162 : if (s->element(static_cast<int>(staffIdx) * VOICES)) {
1405 162 : empty = false;
1406 162 : break;
1407 : }
1408 : }
1409 162 : if (empty) {
1410 0 : if ((m->ticks() == m->timesig())) {
1411 0 : Segment* s = m->getSegment(SegmentType::ChordRest, m->tick());
1412 0 : Rest* rest = Factory::createRest(s);
1413 0 : rest->setDurationType(DurationType::V_MEASURE);
1414 0 : rest->setTicks(m->ticks());
1415 0 : rest->setTrack(static_cast<int>(staffIdx) * VOICES);
1416 0 : s->add(rest);
1417 : } else {
1418 0 : auto durList = toDurationList(m->ticks(), true);
1419 0 : int tickOffset = 0;
1420 0 : for (auto d : durList) {
1421 0 : Segment* s = m->getSegment(SegmentType::ChordRest, m->tick() + Fraction::fromTicks(tickOffset));
1422 0 : Rest* rest = Factory::createRest(s);
1423 0 : rest->setDurationType(d);
1424 0 : rest->setTrack(static_cast<int>(staffIdx) * VOICES);
1425 0 : s->add(rest);
1426 0 : tickOffset += d.ticks().ticks();
1427 : }
1428 0 : }
1429 : }
1430 : }
1431 : }
1432 : // score->connectSlurs();
1433 29 : score->connectTies();
1434 29 : score->updateTicksAndTimeSigMap();
1435 29 : score->invalidateRepeatList();
1436 29 : score->setLayoutAll();
1437 : }
1438 :
1439 : //---------------------------------------------------------
1440 : // Capella
1441 : //---------------------------------------------------------
1442 :
1443 39 : Capella::Capella()
1444 : {
1445 39 : author = 0;
1446 39 : keywords = 0;
1447 39 : comment = 0;
1448 39 : }
1449 :
1450 39 : Capella::~Capella()
1451 : {
1452 39 : delete[] author;
1453 39 : delete[] keywords;
1454 39 : delete[] comment;
1455 39 : }
1456 :
1457 : //---------------------------------------------------------
1458 : // SlurObj::read
1459 : //---------------------------------------------------------
1460 :
1461 3 : void SlurObj::read()
1462 : {
1463 3 : BasicDrawObj::read();
1464 15 : for (int i = 0; i < 4; ++i) {
1465 12 : bezierPoint[i].setX(cap->readInt());
1466 12 : bezierPoint[i].setY(cap->readInt());
1467 : }
1468 3 : color = cap->readColor();
1469 3 : nEnd = cap->readByte();
1470 3 : nMid = cap->readByte();
1471 3 : nDotDist = cap->readByte();
1472 3 : nDotWidth = cap->readByte();
1473 : // CAPELLA_TRACE("SlurObj nEnd %d nMid %d nDotDist %d nDotWidth %d",
1474 : // nEnd, nMid, nDotDist, nDotWidth);
1475 3 : }
1476 :
1477 : //---------------------------------------------------------
1478 : // read
1479 : //---------------------------------------------------------
1480 :
1481 2 : void TextObj::read()
1482 : {
1483 2 : BasicRectObj::read();
1484 2 : unsigned size = cap->readUnsigned();
1485 2 : cap->verifyLength(size);
1486 0 : std::vector<char> vtxt(size + 1);
1487 0 : char* txt = vtxt.data();
1488 0 : if (!cap->read(txt, size)) {
1489 0 : throw Capella::Error::BAD_FORMAT;
1490 : }
1491 0 : txt[size] = 0;
1492 0 : text = QString(txt);
1493 : // CAPELLA_TRACE("read textObj len %d <%s>", size, txt);
1494 0 : }
1495 :
1496 : //---------------------------------------------------------
1497 : // read
1498 : //---------------------------------------------------------
1499 :
1500 0 : void SimpleTextObj::read()
1501 : {
1502 0 : BasicDrawObj::read();
1503 0 : relPos = cap->readPoint();
1504 0 : align = cap->readByte();
1505 0 : _font = cap->readFont();
1506 0 : _text = cap->readQString();
1507 : // CAPELLA_TRACE("read SimpletextObj(%f,%f) len %zd <%s>",
1508 : // relPos.x(), relPos.y(), _text.length(), qPrintable(_text));
1509 0 : }
1510 :
1511 : //---------------------------------------------------------
1512 : // LineObj::read
1513 : //---------------------------------------------------------
1514 :
1515 14 : void LineObj::read()
1516 : {
1517 14 : BasicDrawObj::read();
1518 14 : pt1 = cap->readPoint();
1519 14 : pt2 = cap->readPoint();
1520 14 : color = cap->readColor();
1521 14 : lineWidth = cap->readByte();
1522 : // CAPELLA_TRACE("LineObj: %f:%f %f:%f width %d", pt1.x(), pt1.y(), pt2.x(), pt2.y(), lineWidth);
1523 14 : }
1524 :
1525 : //---------------------------------------------------------
1526 : // BracketObj::read
1527 : //---------------------------------------------------------
1528 :
1529 14 : void BracketObj::read()
1530 : {
1531 14 : LineObj::read();
1532 14 : orientation = cap->readByte();
1533 14 : number = cap->readByte();
1534 14 : }
1535 :
1536 : //---------------------------------------------------------
1537 : // GroupObj::read
1538 : //---------------------------------------------------------
1539 :
1540 0 : void GroupObj::read()
1541 : {
1542 0 : BasicDrawObj::read();
1543 0 : relPos = cap->readPoint();
1544 0 : objects = cap->readDrawObjectArray();
1545 0 : }
1546 :
1547 : //---------------------------------------------------------
1548 : // TransposableObj::read
1549 : //---------------------------------------------------------
1550 :
1551 0 : void TransposableObj::read()
1552 : {
1553 0 : BasicDrawObj::read();
1554 0 : relPos = cap->readPoint();
1555 0 : b = cap->readByte();
1556 0 : if (b != 12 && b != 21) {
1557 0 : LOGD("TransposableObj::read: warning: unknown drawObjectArray size of %d", b);
1558 : }
1559 0 : variants = cap->readDrawObjectArray();
1560 0 : IF_ASSERT_FAILED_X(variants.size() == b, QString::asprintf("variants.size %lld, expected %d", variants.size(), b)) {
1561 0 : throw Capella::Error::BAD_FORMAT;
1562 : }
1563 0 : /*int nRefNote =*/ cap->readInt();
1564 0 : }
1565 :
1566 : //---------------------------------------------------------
1567 : // MetafileObj::read
1568 : //---------------------------------------------------------
1569 :
1570 2 : void MetafileObj::read()
1571 : {
1572 2 : BasicRectObj::read();
1573 2 : unsigned size = cap->readUnsigned();
1574 2 : cap->verifyLength(size);
1575 0 : std::vector<char> vEnhMetaFileBits(size);
1576 0 : char* enhMetaFileBits = vEnhMetaFileBits.data();
1577 0 : if (!cap->read(enhMetaFileBits, size)) {
1578 0 : throw Capella::Error::BAD_FORMAT;
1579 : }
1580 : // CAPELLA_TRACE("MetaFileObj::read %d bytes", size);
1581 0 : }
1582 :
1583 : //---------------------------------------------------------
1584 : // RectEllipseObj::read
1585 : //---------------------------------------------------------
1586 :
1587 0 : void RectEllipseObj::read()
1588 : {
1589 0 : LineObj::read();
1590 0 : radius = cap->readInt();
1591 0 : bFilled = cap->readByte();
1592 0 : clrFill = cap->readColor();
1593 0 : }
1594 :
1595 : //---------------------------------------------------------
1596 : // PolygonObj::read
1597 : //---------------------------------------------------------
1598 :
1599 0 : void PolygonObj::read()
1600 : {
1601 0 : BasicDrawObj::read();
1602 :
1603 0 : unsigned nPoints = cap->readUnsigned();
1604 0 : for (unsigned i = 0; i < nPoints; ++i) {
1605 0 : cap->readPoint();
1606 : }
1607 :
1608 0 : bFilled = cap->readByte();
1609 0 : lineWidth = cap->readByte();
1610 0 : clrFill = cap->readColor();
1611 0 : clrLine = cap->readColor();
1612 0 : }
1613 :
1614 : //---------------------------------------------------------
1615 : // WavyLineObj::read
1616 : //---------------------------------------------------------
1617 :
1618 0 : void WavyLineObj::read()
1619 : {
1620 0 : LineObj::read();
1621 0 : waveLen = cap->readByte();
1622 0 : adapt = cap->readByte();
1623 0 : }
1624 :
1625 : //---------------------------------------------------------
1626 : // NotelinesObj::read
1627 : //---------------------------------------------------------
1628 :
1629 0 : void NotelinesObj::read()
1630 : {
1631 0 : BasicDrawObj::read();
1632 :
1633 0 : x0 = cap->readInt();
1634 0 : x1 = cap->readInt();
1635 0 : y = cap->readInt();
1636 0 : color = cap->readColor();
1637 :
1638 0 : unsigned char b = cap->readByte();
1639 0 : switch (b) {
1640 0 : case 1: break; // Einlinienzeile
1641 0 : case 2: break; // Standard (5 Linien)
1642 0 : default: {
1643 0 : IF_ASSERT_FAILED(b == 0) {
1644 0 : throw Capella::Error::BAD_FORMAT;
1645 : }
1646 : char lines[11];
1647 0 : cap->read(lines, 11);
1648 0 : break;
1649 : }
1650 : }
1651 0 : }
1652 :
1653 : //---------------------------------------------------------
1654 : // VoltaObj::read
1655 : //---------------------------------------------------------
1656 :
1657 0 : void VoltaObj::read()
1658 : {
1659 0 : BasicDrawObj::read();
1660 :
1661 0 : x0 = cap->readInt();
1662 0 : x1 = cap->readInt();
1663 0 : y = cap->readInt();
1664 0 : color = cap->readColor();
1665 :
1666 0 : unsigned char f = cap->readByte();
1667 0 : bLeft = (f & 1) != 0; // links abgeknickt
1668 0 : bRight = (f & 2) != 0; // rechts abgeknickt
1669 0 : bDotted = (f & 4) != 0;
1670 0 : allNumbers = (f & 8) != 0;
1671 :
1672 0 : unsigned char numbers = cap->readByte();
1673 0 : from = numbers & 0x0F;
1674 0 : to = (numbers >> 4) & 0x0F;
1675 : CAPELLA_TRACE("VoltaObj::read x0 %d x1 %d y %d bLeft %d bRight %d bDotted %d allNumbers %d from %d to %d",
1676 : x0, x1, y, bLeft, bRight, bDotted, allNumbers, from, to);
1677 0 : }
1678 :
1679 : //---------------------------------------------------------
1680 : // GuitarObj::read
1681 : //---------------------------------------------------------
1682 :
1683 0 : void GuitarObj::read()
1684 : {
1685 0 : BasicDrawObj::read();
1686 0 : relPos = cap->readPoint();
1687 0 : color = cap->readColor();
1688 0 : flags = cap->readWord();
1689 0 : strings = cap->readDWord(); // 8 Saiten in 8 Halbbytes
1690 0 : }
1691 :
1692 : //---------------------------------------------------------
1693 : // TrillObj::read
1694 : //---------------------------------------------------------
1695 :
1696 0 : void TrillObj::read()
1697 : {
1698 0 : BasicDrawObj::read();
1699 0 : x0 = cap->readInt();
1700 0 : x1 = cap->readInt();
1701 0 : y = cap->readInt();
1702 0 : color = cap->readColor();
1703 0 : trillSign = cap->readByte();
1704 0 : }
1705 :
1706 : //---------------------------------------------------------
1707 : // readDrawObjectArray
1708 : //---------------------------------------------------------
1709 :
1710 36 : QList<BasicDrawObj*> Capella::readDrawObjectArray()
1711 : {
1712 36 : QList<BasicDrawObj*> ol;
1713 36 : int n = readUnsigned(); // draw obj array
1714 :
1715 : // CAPELLA_TRACE("readDrawObjectArray %d elements", n);
1716 53 : for (int i = 0; i < n; ++i) {
1717 21 : CapellaType type = CapellaType(readByte());
1718 :
1719 : // LOGD(" readDrawObject %d of %d, type %d", i, n, type);
1720 21 : switch (type) {
1721 0 : case CapellaType::GROUP: {
1722 0 : GroupObj* o = new GroupObj(this);
1723 0 : o->read();
1724 0 : ol.append(o);
1725 : }
1726 0 : break;
1727 0 : case CapellaType::TRANSPOSABLE: {
1728 0 : TransposableObj* o = new TransposableObj(this);
1729 0 : o->read();
1730 0 : ol.append(o);
1731 : }
1732 0 : break;
1733 2 : case CapellaType::METAFILE: {
1734 2 : MetafileObj* o = new MetafileObj(this);
1735 2 : o->read();
1736 0 : ol.append(o);
1737 : }
1738 0 : break;
1739 0 : case CapellaType::SIMPLE_TEXT: {
1740 0 : SimpleTextObj* o = new SimpleTextObj(this);
1741 0 : o->read();
1742 0 : ol.append(o);
1743 : }
1744 0 : break;
1745 2 : case CapellaType::TEXT: {
1746 2 : TextObj* o = new TextObj(this);
1747 2 : o->read();
1748 0 : ol.append(o);
1749 : }
1750 0 : break;
1751 0 : case CapellaType::RECT_ELLIPSE: {
1752 0 : RectEllipseObj* o = new RectEllipseObj(this);
1753 0 : o->read();
1754 0 : ol.append(o);
1755 : }
1756 0 : break;
1757 0 : case CapellaType::LINE: {
1758 0 : LineObj* o = new LineObj(this);
1759 0 : o->read();
1760 0 : ol.append(o);
1761 : }
1762 0 : break;
1763 0 : case CapellaType::POLYGON: {
1764 0 : PolygonObj* o = new PolygonObj(this);
1765 0 : o->read();
1766 0 : ol.append(o);
1767 : }
1768 0 : break;
1769 0 : case CapellaType::WAVY_LINE: {
1770 0 : WavyLineObj* o = new WavyLineObj(this);
1771 0 : o->read();
1772 0 : ol.append(o);
1773 : }
1774 0 : break;
1775 3 : case CapellaType::SLUR: {
1776 3 : SlurObj* o = new SlurObj(this);
1777 3 : o->read();
1778 3 : ol.append(o);
1779 : }
1780 3 : break;
1781 0 : case CapellaType::NOTE_LINES: {
1782 0 : NotelinesObj* o = new NotelinesObj(this);
1783 0 : o->read();
1784 0 : ol.append(o);
1785 : }
1786 0 : break;
1787 0 : case CapellaType::WEDGE: {
1788 0 : WedgeObj* o = new WedgeObj(this);
1789 0 : o->read();
1790 0 : ol.append(o);
1791 : }
1792 0 : break;
1793 0 : case CapellaType::VOLTA: {
1794 0 : VoltaObj* o = new VoltaObj(this);
1795 0 : o->read();
1796 0 : ol.append(o);
1797 : }
1798 0 : break;
1799 14 : case CapellaType::BRACKET: {
1800 14 : BracketObj* o = new BracketObj(this);
1801 14 : o->read();
1802 14 : ol.append(o);
1803 : }
1804 14 : break;
1805 0 : case CapellaType::GUITAR: {
1806 0 : GuitarObj* o = new GuitarObj(this);
1807 0 : o->read();
1808 0 : ol.append(o);
1809 : }
1810 0 : break;
1811 0 : case CapellaType::TRILL: {
1812 0 : TrillObj* o = new TrillObj(this);
1813 0 : o->read();
1814 0 : ol.append(o);
1815 : }
1816 0 : break;
1817 0 : default:
1818 0 : IF_ASSERT_FAILED_X(false, QString::asprintf("readDrawObjectArray unsupported type %d", int(type))) {
1819 : throw Capella::Error::BAD_FORMAT;
1820 : }
1821 : break;
1822 : }
1823 : }
1824 32 : return ol;
1825 4 : }
1826 :
1827 : //---------------------------------------------------------
1828 : // BasicDrawObj
1829 : //---------------------------------------------------------
1830 :
1831 21 : void BasicDrawObj::read()
1832 : {
1833 21 : modeX = cap->readByte(); // anchor mode
1834 21 : modeY = cap->readByte();
1835 21 : distY = cap->readByte();
1836 21 : flags = cap->readByte();
1837 21 : nRefNote = cap->readInt();
1838 21 : short range = cap->readWord();
1839 21 : nNotes = range & 0x0fff;
1840 21 : background = range & 0x1000;
1841 21 : pageRange = (range >> 13) & 0x7;
1842 : CAPELLA_TRACE("BasicDrawObj::read modeX %d modeY %d distY %d flags %d nRefNote %d nNotes %d background %d pageRange %d",
1843 : modeX, modeY, distY, flags, nRefNote, nNotes, background, pageRange);
1844 21 : }
1845 :
1846 : //---------------------------------------------------------
1847 : // BasicRectObj
1848 : //---------------------------------------------------------
1849 :
1850 4 : void BasicRectObj::read()
1851 : {
1852 4 : BasicDrawObj::read();
1853 4 : relPos = cap->readPoint();
1854 4 : width = cap->readInt();
1855 4 : yxRatio = cap->readInt();
1856 4 : height = (width * yxRatio) / 0x10000;
1857 4 : }
1858 :
1859 : //---------------------------------------------------------
1860 : // read
1861 : //---------------------------------------------------------
1862 :
1863 695 : void BasicDurationalObj::read()
1864 : {
1865 695 : unsigned char b = cap->readByte();
1866 695 : IF_ASSERT_FAILED(!(b & 0x80)) {
1867 0 : throw Capella::Error::BAD_FORMAT;
1868 : }
1869 695 : nDots = b & 0x03;
1870 695 : noDuration = b & 0x04;
1871 695 : postGrace = b & 0x08;
1872 695 : bSmall = b & 0x10;
1873 695 : invisible = b & 0x20;
1874 695 : notBlack = b & 0x40;
1875 :
1876 695 : color = notBlack ? cap->readColor() : Qt::black;
1877 :
1878 695 : unsigned char c = cap->readByte();
1879 695 : IF_ASSERT_FAILED(!(c & 0x80)) {
1880 0 : throw Capella::Error::BAD_FORMAT;
1881 : }
1882 695 : t = TIMESTEP(c & 0x0f);
1883 695 : horizontalShift = (c & 0x10) ? cap->readInt() : 0;
1884 695 : tupletDenominator = 0;
1885 695 : tripartite = 0;
1886 695 : isProlonging = 0;
1887 695 : if (c & 0x20) {
1888 119 : unsigned char tuplet = cap->readByte();
1889 119 : tupletDenominator = tuplet & 0x0f;
1890 119 : tripartite = (tuplet & 0x10) != 0;
1891 119 : isProlonging = (tuplet & 0x20) != 0;
1892 119 : if (tuplet & 0xc0) {
1893 102 : LOGD("bad tuplet value 0x%02x", tuplet);
1894 : }
1895 : }
1896 695 : if (c & 0x40) {
1897 17 : objects = cap->readDrawObjectArray();
1898 : }
1899 : CAPELLA_TRACE("DurationObj ndots %d nodur %d postgr %d bsm %d inv %d notbl %d t %d hsh %d den %d trp %d ispro %d",
1900 : nDots, noDuration, postGrace, bSmall, invisible, notBlack, int(t), horizontalShift, tupletDenominator, tripartite, isProlonging
1901 : );
1902 695 : }
1903 :
1904 : //---------------------------------------------------------
1905 : // RestObj
1906 : //---------------------------------------------------------
1907 :
1908 3 : RestObj::RestObj(Capella* c)
1909 3 : : BasicDurationalObj(c), NoteObj(CapellaNoteObjectType::REST)
1910 : {
1911 3 : cap = c;
1912 3 : fullMeasures = 0;
1913 3 : vertShift = 0;
1914 3 : }
1915 :
1916 : //---------------------------------------------------------
1917 : // read
1918 : //---------------------------------------------------------
1919 :
1920 0 : void RestObj::read()
1921 : {
1922 0 : BasicDurationalObj::read();
1923 0 : unsigned char b = cap->readByte();
1924 0 : bool bMultiMeasures = b & 1;
1925 0 : bVerticalCentered = b & 2;
1926 0 : bool bAddVerticalShift = b & 4;
1927 0 : if (b & 0xf8) {
1928 0 : ASSERT_X(QString::asprintf("RestObj: res. bits 0x%02x", b));
1929 : }
1930 0 : fullMeasures = bMultiMeasures ? cap->readUnsigned() : 0;
1931 0 : vertShift = bAddVerticalShift ? cap->readInt() : 0;
1932 0 : }
1933 :
1934 : //---------------------------------------------------------
1935 : // ChordObj
1936 : //---------------------------------------------------------
1937 :
1938 1076 : ChordObj::ChordObj(Capella* c)
1939 1076 : : BasicDurationalObj(c), NoteObj(CapellaNoteObjectType::CHORD)
1940 : {
1941 1076 : cap = c;
1942 1076 : beamMode = CapBeamMode::AUTO;
1943 1076 : }
1944 :
1945 : //---------------------------------------------------------
1946 : // read
1947 : //---------------------------------------------------------
1948 :
1949 695 : void ChordObj::read()
1950 : {
1951 695 : stemDir = StemDir::AUTO;
1952 695 : dStemLength = 0;
1953 695 : nTremoloBars = 0;
1954 695 : articulation = 0;
1955 695 : leftTie = false;
1956 695 : rightTie = false;
1957 695 : beamShift = 0;
1958 695 : beamSlope = 0;
1959 :
1960 695 : BasicDurationalObj::read();
1961 :
1962 695 : unsigned char flags = cap->readByte();
1963 695 : beamMode = (flags & 0x01) ? CapBeamMode(cap->readByte()) : CapBeamMode::AUTO;
1964 695 : notationStave = (flags & 0x02) ? cap->readChar() : 0;
1965 695 : IF_ASSERT_FAILED(notationStave >= -1 && notationStave <= 1) {
1966 0 : throw Capella::Error::BAD_FORMAT;
1967 : }
1968 :
1969 695 : if (flags & 0x04) {
1970 0 : stemDir = StemDir(cap->readChar());
1971 0 : dStemLength = cap->readChar();
1972 : }
1973 695 : if (flags & 0x08) {
1974 0 : nTremoloBars = cap->readByte();
1975 0 : articulation = cap->readByte();
1976 : }
1977 695 : if (flags & 0x10) {
1978 0 : unsigned char b = cap->readByte();
1979 0 : leftTie = b & 1;
1980 0 : rightTie = b & 2;
1981 : }
1982 695 : if (flags & 0x20) {
1983 0 : beamShift = cap->readChar();
1984 0 : beamSlope = cap->readChar();
1985 : }
1986 695 : if (flags & 0x40) {
1987 0 : unsigned nVerses = cap->readUnsigned();
1988 0 : for (unsigned int i = 0; i < nVerses; ++i) {
1989 0 : bool bVerse = cap->readByte();
1990 0 : if (bVerse) {
1991 0 : Verse v;
1992 0 : unsigned char b = cap->readByte();
1993 0 : v.leftAlign = b & 1;
1994 0 : v.extender = b & 2;
1995 0 : v.hyphen = b & 4;
1996 0 : v.num = i;
1997 0 : if (b & 8) {
1998 0 : v.verseNumber = cap->readQString();
1999 : }
2000 0 : if (b & 16) {
2001 0 : v.text = cap->readQString();
2002 : }
2003 0 : verse.append(v);
2004 0 : }
2005 : }
2006 : }
2007 695 : unsigned nNotes = cap->readUnsigned();
2008 1390 : for (unsigned int i = 0; i < nNotes; ++i) {
2009 : CNote n;
2010 695 : n.explAlteration = 0;
2011 695 : char c = cap->readChar();
2012 695 : bool bit7 = c & 0x80;
2013 695 : bool bit6 = c & 0x40;
2014 695 : n.pitch = (signed char)c;
2015 695 : if (bit7 != bit6) {
2016 0 : n.explAlteration = 2;
2017 0 : n.pitch ^= 0x80;
2018 : }
2019 695 : unsigned char b = cap->readByte();
2020 695 : n.headType = b & 7;
2021 695 : if (n.headType == 6) {
2022 0 : n.headType = 0;
2023 0 : n.headGroup = int(NoteHeadGroup::HEAD_CROSS);
2024 : } else {
2025 695 : n.headGroup = int(NoteHeadGroup::HEAD_NORMAL);
2026 : }
2027 695 : n.alteration = ((b >> 3) & 7) - 2; // -2 -- +2
2028 695 : if (b & 0x40) {
2029 0 : n.explAlteration = 1;
2030 : }
2031 695 : n.silent = b & 0x80;
2032 : CAPELLA_TRACE("ChordObj::read() note pitch %d explAlt %d head group %d %d alt %d silent %d",
2033 : n.pitch, n.explAlteration, n.headType, n.headGroup, n.alteration, n.silent);
2034 695 : notes.append(n);
2035 : }
2036 695 : }
2037 :
2038 : //---------------------------------------------------------
2039 : // read
2040 : // return false on error
2041 : //---------------------------------------------------------
2042 :
2043 10563 : bool Capella::read(void* p, qint64 len)
2044 : {
2045 10563 : if (len == 0) {
2046 133 : return true;
2047 : }
2048 10430 : qint64 rv = f->read((char*)p, len);
2049 10430 : if (rv != len) {
2050 0 : return false;
2051 : }
2052 10430 : curPos += len;
2053 10430 : return true;
2054 : }
2055 :
2056 : //---------------------------------------------------------
2057 : // verifyLength
2058 : //---------------------------------------------------------
2059 :
2060 177 : void Capella::verifyLength(unsigned len) const
2061 : {
2062 177 : if (len > f->bytesAvailable()) {
2063 6 : throw Capella::Error::BAD_FORMAT;
2064 : }
2065 171 : }
2066 :
2067 : //---------------------------------------------------------
2068 : // readByte
2069 : //---------------------------------------------------------
2070 :
2071 7249 : unsigned char Capella::readByte()
2072 : {
2073 : unsigned char c;
2074 7249 : read(&c, 1);
2075 7249 : return c;
2076 : }
2077 :
2078 : //---------------------------------------------------------
2079 : // readChar
2080 : //---------------------------------------------------------
2081 :
2082 900 : char Capella::readChar()
2083 : {
2084 : char c;
2085 900 : read(&c, 1);
2086 900 : return c;
2087 : }
2088 :
2089 : //---------------------------------------------------------
2090 : // readWord
2091 : //---------------------------------------------------------
2092 :
2093 21 : short Capella::readWord()
2094 : {
2095 : short c;
2096 21 : read(&c, 2);
2097 21 : return c;
2098 : }
2099 :
2100 : //---------------------------------------------------------
2101 : // readDWord
2102 : //---------------------------------------------------------
2103 :
2104 0 : int Capella::readDWord()
2105 : {
2106 : int c;
2107 0 : read(&c, 4);
2108 0 : return c;
2109 : }
2110 :
2111 : //---------------------------------------------------------
2112 : // readLong
2113 : //---------------------------------------------------------
2114 :
2115 95 : int Capella::readLong()
2116 : {
2117 : int c;
2118 95 : read(&c, 4);
2119 95 : return c;
2120 : }
2121 :
2122 : //---------------------------------------------------------
2123 : // readUnsigned
2124 : //---------------------------------------------------------
2125 :
2126 1464 : unsigned Capella::readUnsigned()
2127 : {
2128 : unsigned char c;
2129 1464 : read(&c, 1);
2130 1464 : if (c == 254) {
2131 : unsigned short s;
2132 60 : read(&s, 2);
2133 60 : return s;
2134 1404 : } else if (c == 255) {
2135 : unsigned s;
2136 6 : read(&s, 4);
2137 6 : return s;
2138 : } else {
2139 1398 : return c;
2140 : }
2141 : }
2142 :
2143 : //---------------------------------------------------------
2144 : // readInt
2145 : //---------------------------------------------------------
2146 :
2147 531 : int Capella::readInt()
2148 : {
2149 : signed char c;
2150 531 : read(&c, 1);
2151 531 : if (c == -128) {
2152 : short s;
2153 30 : read(&s, 2);
2154 30 : return s;
2155 501 : } else if (c == 127) {
2156 : int s;
2157 0 : read(&s, 4);
2158 0 : return s;
2159 : } else {
2160 501 : return c;
2161 : }
2162 : }
2163 :
2164 : //---------------------------------------------------------
2165 : // readString -- read Capella string into newly allocated char buffer
2166 : // note that no carriage return / newline interpretation is done
2167 : //---------------------------------------------------------
2168 :
2169 173 : char* Capella::readString()
2170 : {
2171 173 : unsigned len = readUnsigned();
2172 173 : verifyLength(len);
2173 171 : char* buffer = new char[static_cast<size_t>(len) + 1];
2174 171 : if (!read(buffer, len)) {
2175 0 : delete[] buffer;
2176 0 : throw Capella::Error::BAD_FORMAT;
2177 : }
2178 171 : buffer[len] = 0;
2179 171 : return buffer;
2180 : }
2181 :
2182 : //---------------------------------------------------------
2183 : // readQString -- read Capella string into QString
2184 : // strings in Capella files may contain \r\n, must remove the \r
2185 : //---------------------------------------------------------
2186 :
2187 114 : QString Capella::readQString()
2188 : {
2189 114 : char* buffer = readString(); // read Capella string
2190 114 : QString res = QString::fromLatin1(buffer); // and copy into QString
2191 114 : res = res.remove(QChar('\r')); // remove the \r
2192 114 : delete [] buffer; // delete memory allocated by readString
2193 114 : return res;
2194 0 : }
2195 :
2196 : //---------------------------------------------------------
2197 : // readColor
2198 : //---------------------------------------------------------
2199 :
2200 285 : QColor Capella::readColor()
2201 : {
2202 : static const int colors[] = {
2203 : 0x000000, // schwarz
2204 : 0x000080, // dunkelrot
2205 : 0x008000, // dunkelgrün
2206 : 0x008080, // ocker
2207 : 0x800000, // dunkelblau
2208 : 0x800080, // purpurrot
2209 : 0x808000, // blaugün
2210 : 0x808080, // grau
2211 : 0xC0C0C0, // hellgrau
2212 : 0x0000FF, // rot
2213 : 0x00FF00, // grün
2214 : 0x00FFFF, // gelb
2215 : 0xFF0000, // blau
2216 : 0xFF00FF, // lila
2217 : 0xFFFF00, // aquamarin
2218 : 0xFFFFFF // weiß
2219 : };
2220 :
2221 285 : QColor c;
2222 285 : unsigned char b = readByte();
2223 285 : if (b >= 16) {
2224 0 : IF_ASSERT_FAILED(b == 255) {
2225 0 : throw Capella::Error::BAD_FORMAT;
2226 : }
2227 0 : int r = readByte();
2228 0 : int g = readByte();
2229 0 : int bi = readByte();
2230 0 : c = QColor(r, g, bi);
2231 : } else {
2232 285 : c = QColor(colors[b]);
2233 : }
2234 285 : return c;
2235 : }
2236 :
2237 : //---------------------------------------------------------
2238 : // readFont
2239 : //---------------------------------------------------------
2240 :
2241 103 : QFont Capella::readFont()
2242 : {
2243 103 : unsigned index = readUnsigned();
2244 103 : if (index == 0) {
2245 19 : int lfHeight = readLong();
2246 19 : /*int lfWidth =*/ readLong();
2247 19 : /*int lfEscapement =*/ readLong();
2248 19 : /*int lfOrientation =*/ readLong();
2249 19 : int lfWeight = readLong();
2250 19 : uchar lfItalic = readByte();
2251 19 : uchar lfUnderline = readByte();
2252 19 : uchar lfStrikeOut = readByte();
2253 19 : /*uchar lfCharSet =*/ readByte();
2254 19 : /*uchar lfOutPrecision =*/ readByte();
2255 19 : /*uchar lfClipPrecision =*/ readByte();
2256 19 : /*uchar lfQuality =*/ readByte();
2257 19 : /*uchar lfPitchAndFamily =*/ readByte();
2258 19 : /*QColor color =*/ readColor();
2259 19 : QString face = readQString();
2260 :
2261 : CAPELLA_TRACE("Font <%s> size %d, weight %d", qPrintable(face), lfHeight, lfWeight);
2262 19 : QFont font(face);
2263 19 : font.setPointSizeF(lfHeight / 1000.0);
2264 19 : font.setItalic(lfItalic);
2265 19 : font.setStrikeOut(lfStrikeOut);
2266 19 : font.setUnderline(lfUnderline);
2267 :
2268 19 : switch (lfWeight) {
2269 0 : case 700: font.setWeight(QFont::Bold);
2270 0 : break;
2271 19 : case 400: font.setWeight(QFont::Normal);
2272 19 : break;
2273 0 : case 0: font.setWeight(QFont::Light);
2274 0 : break;
2275 : }
2276 19 : fonts.append(font);
2277 19 : return font;
2278 19 : }
2279 84 : index -= 1;
2280 84 : if (index >= fonts.size()) {
2281 0 : LOGD("illegal font index %u (max %lld)", index, fonts.size() - 1);
2282 0 : return QFont();
2283 : }
2284 84 : return fonts[index];
2285 : }
2286 :
2287 : //---------------------------------------------------------
2288 : // readStaveLayout
2289 : //---------------------------------------------------------
2290 :
2291 19 : void Capella::readStaveLayout(CapStaffLayout* sl, int idx)
2292 : {
2293 19 : sl->barlineMode = readByte();
2294 19 : sl->noteLines = readByte();
2295 19 : switch (sl->noteLines) {
2296 0 : case 1: break; // one line
2297 19 : case 2: break; // five lines
2298 0 : default:
2299 : {
2300 : char lines[11];
2301 0 : f->read(lines, 11);
2302 0 : curPos += 11;
2303 : }
2304 0 : break;
2305 : }
2306 : CAPELLA_TRACE("StaffLayout %d: barlineMode %d noteLines %d", idx, sl->barlineMode, sl->noteLines);
2307 :
2308 19 : sl->bSmall = readByte();
2309 : CAPELLA_TRACE("staff size small %d", sl->bSmall);
2310 :
2311 19 : sl->topDist = readInt();
2312 19 : sl->btmDist = readInt();
2313 19 : sl->groupDist = readInt();
2314 19 : sl->barlineFrom = readByte();
2315 19 : sl->barlineTo = readByte();
2316 : // LOGD("topDist %d btmDist %d groupDist %d barlineFrom %d barlineTo %d",
2317 : // sl->topDist, sl->btmDist, sl->groupDist, sl->barlineFrom, sl->barlineTo);
2318 :
2319 19 : unsigned char clef = readByte();
2320 19 : sl->form = Form(clef & 7);
2321 19 : sl->line = ClefLine((clef >> 3) & 7);
2322 19 : sl->oct = Oct((clef >> 6));
2323 : CAPELLA_TRACE(" clef %x form %d, line %d, oct %d", clef, int(sl->form), int(sl->line), int(sl->oct));
2324 :
2325 : // Schlagzeuginformation
2326 19 : unsigned char b = readByte();
2327 19 : sl->bPercussion = b & 1; // Schlagzeugkanal verwenden
2328 19 : sl->bSoundMapIn = b & 2;
2329 19 : sl->bSoundMapOut = b & 4;
2330 19 : if (sl->bSoundMapIn) { // Umleitungstabelle für Eingabe vom Keyboard
2331 0 : uchar iMin = readByte();
2332 0 : uchar n = readByte();
2333 0 : IF_ASSERT_FAILED(n > 0 && iMin + n <= 128) {
2334 0 : throw Capella::Error::BAD_FORMAT;
2335 : }
2336 0 : f->read(sl->soundMapIn, n);
2337 0 : curPos += n;
2338 : }
2339 19 : if (sl->bSoundMapOut) { // Umleitungstabelle für das Vorspielen
2340 0 : unsigned char iMin = readByte();
2341 0 : unsigned char n = readByte();
2342 0 : IF_ASSERT_FAILED(n > 0 && iMin + n <= 128) {
2343 0 : throw Capella::Error::BAD_FORMAT;
2344 : }
2345 0 : f->read(sl->soundMapOut, n);
2346 0 : curPos += n;
2347 : }
2348 19 : sl->sound = readInt();
2349 19 : sl->volume = readInt();
2350 19 : sl->transp = readInt();
2351 : CAPELLA_TRACE(" sound %d vol %d transp %d", sl->sound, sl->volume, sl->transp);
2352 :
2353 19 : sl->descr = readQString();
2354 19 : sl->name = readQString();
2355 19 : sl->abbrev = readQString();
2356 19 : sl->intermediateName = readQString();
2357 19 : sl->intermediateAbbrev = readQString();
2358 : CAPELLA_TRACE(" descr <%s> name <%s> abbrev <%s> iname <%s> iabbrev <%s>",
2359 : qPrintable(sl->descr), qPrintable(sl->name), qPrintable(sl->abbrev),
2360 : qPrintable(sl->intermediateName), qPrintable(sl->intermediateAbbrev));
2361 19 : }
2362 :
2363 : //---------------------------------------------------------
2364 : // readLayout
2365 : //---------------------------------------------------------
2366 :
2367 19 : void Capella::readLayout()
2368 : {
2369 19 : smallLineDist = double(readInt()) / 100;
2370 19 : normalLineDist = double(readInt()) / 100;
2371 : CAPELLA_TRACE("Capella::readLayout(): smallLineDist %g normalLineDist %g", smallLineDist, normalLineDist);
2372 :
2373 19 : topDist = readInt();
2374 19 : interDist = readInt();
2375 : CAPELLA_TRACE("Capella::readLayout(): topDist %d", topDist);
2376 :
2377 19 : txtAlign = readByte(); // Stimmenbezeichnungen 0=links, 1=zentriert, 2=rechts
2378 19 : adjustVert = readByte(); // 0=nein, 1=außer letzte Seite, 3=alle Seiten
2379 :
2380 19 : unsigned char b = readByte();
2381 19 : IF_ASSERT_FAILED(!(b & 0xFC)) { // bits 2...7 reserviert
2382 0 : throw Capella::Error::BAD_FORMAT;
2383 : }
2384 19 : redundantKeys = b & 1;
2385 19 : modernDoubleNote = b & 2;
2386 :
2387 19 : bSystemSeparators = readByte();
2388 19 : nUnnamed = readInt();
2389 :
2390 19 : namesFont = readFont();
2391 :
2392 : // Musterzeilen
2393 19 : unsigned nStaveLayouts = readUnsigned();
2394 :
2395 : // CAPELLA_TRACE("%d staves", nStaveLayouts);
2396 :
2397 38 : for (unsigned iStave = 0; iStave < nStaveLayouts; iStave++) {
2398 19 : CapStaffLayout* sl = new CapStaffLayout;
2399 19 : readStaveLayout(sl, iStave);
2400 19 : _staffLayouts.append(sl);
2401 : }
2402 :
2403 : // system brackets:
2404 19 : unsigned n = readUnsigned(); // number of brackets
2405 19 : for (unsigned int i = 0; i < n; i++) {
2406 : CapBracket cb;
2407 0 : cb.from = readInt();
2408 0 : cb.to = readInt();
2409 0 : cb.curly = readByte();
2410 : // CAPELLA_TRACE("Bracket%d %d-%d curly %d", i, b.from, b.to, b.curly);
2411 0 : brackets.append(cb);
2412 : }
2413 : // CAPELLA_TRACE("Capella::readLayout(): done");
2414 19 : }
2415 :
2416 : //---------------------------------------------------------
2417 : // readExtra
2418 : //---------------------------------------------------------
2419 :
2420 1017 : void Capella::readExtra()
2421 : {
2422 1017 : uchar n = readByte();
2423 1017 : if (n) {
2424 : CAPELLA_TRACE("Capella::readExtra(%d)", n);
2425 849 : for (int i = 0; i < n; ++i) {
2426 763 : readByte();
2427 : }
2428 : }
2429 1017 : }
2430 :
2431 : //---------------------------------------------------------
2432 : // CapClef::read
2433 : //---------------------------------------------------------
2434 :
2435 55 : void CapClef::read()
2436 : {
2437 55 : unsigned char b = cap->readByte();
2438 55 : form = Form(b & 7);
2439 55 : line = ClefLine((b >> 3) & 7);
2440 55 : oct = Oct(b >> 6);
2441 : CAPELLA_TRACE("Clef::read form %d line %d oct %d", int(form), int(line), int(oct));
2442 55 : }
2443 :
2444 : //---------------------------------------------------------
2445 : // clef
2446 : //---------------------------------------------------------
2447 :
2448 88 : ClefType CapClef::clef() const
2449 : {
2450 88 : return clefType(form, line, oct);
2451 : }
2452 :
2453 88 : ClefType CapClef::clefType(Form form, ClefLine line, Oct oct)
2454 : {
2455 88 : int idx = int(form) + (int(line) << 3) + (int(oct) << 5);
2456 88 : switch (idx) {
2457 82 : case int(Form::G) + (int(ClefLine::L2) << 3) + (int(Oct::OCT_NULL) << 5): return ClefType::G;
2458 0 : case int(Form::G) + (int(ClefLine::L2) << 3) + (int(Oct::OCT_ALTA) << 5): return ClefType::G8_VA;
2459 1 : case int(Form::G) + (int(ClefLine::L2) << 3) + (int(Oct::OCT_BASSA) << 5): return ClefType::G8_VB;
2460 :
2461 0 : case int(Form::C) + (int(ClefLine::L1) << 3) + (int(Oct::OCT_NULL) << 5): return ClefType::C1;
2462 0 : case int(Form::C) + (int(ClefLine::L2) << 3) + (int(Oct::OCT_NULL) << 5): return ClefType::C2;
2463 0 : case int(Form::C) + (int(ClefLine::L3) << 3) + (int(Oct::OCT_NULL) << 5): return ClefType::C3;
2464 0 : case int(Form::C) + (int(ClefLine::L4) << 3) + (int(Oct::OCT_NULL) << 5): return ClefType::C4;
2465 0 : case int(Form::C) + (int(ClefLine::L4) << 3) + (int(Oct::OCT_BASSA) << 5): return ClefType::C4_8VB;
2466 0 : case int(Form::C) + (int(ClefLine::L5) << 3) + (int(Oct::OCT_NULL) << 5): return ClefType::C5;
2467 :
2468 5 : case int(Form::F) + (int(ClefLine::L4) << 3) + (int(Oct::OCT_NULL) << 5): return ClefType::F;
2469 0 : case int(Form::F) + (int(ClefLine::L4) << 3) + (int(Oct::OCT_BASSA) << 5): return ClefType::F8_VB;
2470 0 : case int(Form::F) + (int(ClefLine::L3) << 3) + (int(Oct::OCT_NULL) << 5): return ClefType::F_B;
2471 0 : case int(Form::F) + (int(ClefLine::L5) << 3) + (int(Oct::OCT_NULL) << 5): return ClefType::F_C;
2472 :
2473 0 : default:
2474 0 : if (form == Form::FORM_NULL) {
2475 0 : return ClefType::INVALID;
2476 : }
2477 0 : LOGD("unknown clef %d %d %d", int(form), int(line), int(oct));
2478 0 : break;
2479 : }
2480 0 : return ClefType::INVALID;
2481 : }
2482 :
2483 : //---------------------------------------------------------
2484 : // CapKey::read
2485 : //---------------------------------------------------------
2486 :
2487 39 : void CapKey::read()
2488 : {
2489 39 : unsigned char b = cap->readByte();
2490 39 : signature = int(b) - 7;
2491 : // LOGD(" Key %d", signature);
2492 39 : }
2493 :
2494 : //---------------------------------------------------------
2495 : // CapMeter::read
2496 : //---------------------------------------------------------
2497 :
2498 19 : void CapMeter::read()
2499 : {
2500 19 : numerator = cap->readByte();
2501 19 : uchar d = cap->readByte();
2502 19 : log2Denom = (d & 0x7f) - 1;
2503 19 : allaBreve = d & 0x80;
2504 : CAPELLA_TRACE(" Meter %d/%d allaBreve %d", numerator, log2Denom, allaBreve);
2505 19 : if (log2Denom > 7 || log2Denom < 0) {
2506 0 : LOGD(" illegal fraction");
2507 : // abort();
2508 0 : log2Denom = 2;
2509 0 : numerator = 4;
2510 : }
2511 19 : }
2512 :
2513 : //---------------------------------------------------------
2514 : // read
2515 : //---------------------------------------------------------
2516 :
2517 0 : void WedgeObj::read()
2518 : {
2519 0 : LineObj::read();
2520 0 : char b = cap->readByte();
2521 0 : height = b & 0x7f;
2522 0 : decresc = b & 0x80;
2523 0 : }
2524 :
2525 : //---------------------------------------------------------
2526 : // CapExplicitBarline::read
2527 : //---------------------------------------------------------
2528 :
2529 0 : void CapExplicitBarline::read()
2530 : {
2531 0 : unsigned char b = cap->readByte();
2532 0 : int type = b & 0x0f;
2533 0 : if (type == 0) {
2534 0 : _type = BarLineType::NORMAL;
2535 0 : } else if (type == 1) {
2536 0 : _type = BarLineType::DOUBLE;
2537 0 : } else if (type == 2) {
2538 0 : _type = BarLineType::END;
2539 0 : } else if (type == 3) {
2540 0 : _type = BarLineType::END_REPEAT;
2541 0 : } else if (type == 4) {
2542 0 : _type = BarLineType::START_REPEAT;
2543 0 : } else if (type == 5) {
2544 0 : _type = BarLineType::END_START_REPEAT;
2545 0 : } else if (type == 6) {
2546 0 : _type = BarLineType::BROKEN;
2547 : } else {
2548 0 : _type = BarLineType::NORMAL; // default
2549 : }
2550 0 : _barMode = b >> 4; // 0 = auto, 1 = nur Zeilen, 2 = durchgezogen
2551 0 : IF_ASSERT_FAILED(_barMode <= 2) {
2552 0 : throw Capella::Error::BAD_FORMAT;
2553 : }
2554 :
2555 : CAPELLA_TRACE(" Expl.Barline type %d mode %d", int(_type), _barMode);
2556 0 : }
2557 :
2558 : //---------------------------------------------------------
2559 : // readVoice
2560 : //---------------------------------------------------------
2561 :
2562 69 : void Capella::readVoice(CapStaff* cs, int idx)
2563 : {
2564 : CAPELLA_TRACE(" readVoice %d", idx);
2565 :
2566 69 : if (readChar() != 'C') {
2567 0 : throw Capella::Error::BAD_VOICE_SIG;
2568 : }
2569 :
2570 69 : CapVoice* v = new CapVoice;
2571 69 : v->voiceNo = idx;
2572 69 : v->y0Lyrics = readByte();
2573 69 : v->dyLyrics = readByte();
2574 69 : v->lyricsFont = readFont();
2575 69 : v->stemDir = readByte();
2576 69 : readExtra();
2577 :
2578 69 : unsigned nNoteObjs = readUnsigned(); // Notenobjekte
2579 862 : for (unsigned i = 0; i < nNoteObjs; i++) {
2580 793 : QColor color = Qt::black;
2581 793 : uchar type = readByte();
2582 : // CAPELLA_TRACE(" Voice %d read object idx %d(%d) type %d", idx, i, nNoteObjs, type);
2583 793 : readExtra();
2584 793 : if ((type != uchar(CapellaNoteObjectType::REST)) && (type != uchar(CapellaNoteObjectType::CHORD))
2585 113 : && (type != uchar(CapellaNoteObjectType::PAGE_BKGR))) {
2586 113 : color = readColor();
2587 : }
2588 :
2589 : // Die anderen Objekttypen haben eine komprimierte Farbcodierung
2590 793 : switch (CapellaNoteObjectType(type)) {
2591 0 : case CapellaNoteObjectType::REST:
2592 : {
2593 0 : RestObj* rest = new RestObj(this);
2594 0 : rest->read();
2595 0 : v->objects.append(rest);
2596 : }
2597 0 : break;
2598 680 : case CapellaNoteObjectType::CHORD:
2599 : case CapellaNoteObjectType::PAGE_BKGR:
2600 : {
2601 680 : ChordObj* chord = new ChordObj(this);
2602 680 : chord->read();
2603 680 : v->objects.append(chord);
2604 : }
2605 680 : break;
2606 55 : case CapellaNoteObjectType::CLEF:
2607 : {
2608 55 : CapClef* clef = new CapClef(this);
2609 55 : clef->read();
2610 55 : v->objects.append(clef);
2611 : }
2612 55 : break;
2613 39 : case CapellaNoteObjectType::KEY:
2614 : {
2615 39 : CapKey* key = new CapKey(this);
2616 39 : key->read();
2617 39 : v->objects.append(key);
2618 : }
2619 39 : break;
2620 19 : case CapellaNoteObjectType::METER:
2621 : {
2622 19 : CapMeter* meter = new CapMeter(this);
2623 19 : meter->read();
2624 19 : v->objects.append(meter);
2625 : }
2626 19 : break;
2627 0 : case CapellaNoteObjectType::EXPL_BARLINE:
2628 : {
2629 0 : CapExplicitBarline* bl = new CapExplicitBarline(this);
2630 0 : bl->read();
2631 : CAPELLA_TRACE("append Expl Barline==========");
2632 0 : v->objects.append(bl);
2633 : }
2634 0 : break;
2635 0 : default:
2636 0 : ASSERT_X(QString::asprintf("bad voice type %d", type));
2637 : }
2638 : }
2639 69 : cs->voices.append(v);
2640 69 : }
2641 :
2642 : //---------------------------------------------------------
2643 : // readStaff
2644 : //---------------------------------------------------------
2645 :
2646 69 : void Capella::readStaff(CapSystem* system)
2647 : {
2648 69 : if (readChar() != 'V') {
2649 0 : throw Capella::Error::BAD_STAFF_SIG;
2650 : }
2651 :
2652 69 : CapStaff* staff = new CapStaff;
2653 : //Meter
2654 69 : staff->numerator = readByte();
2655 69 : uchar d = readByte();
2656 69 : staff->log2Denom = (d & 0x7f) - 1;
2657 69 : staff->allaBreve = d & 0x80;
2658 : CAPELLA_TRACE(" CapStaff meter %d/%d allaBreve %d", staff->numerator, staff->log2Denom, staff->allaBreve);
2659 69 : if (staff->log2Denom > 7 || staff->log2Denom < 0) {
2660 0 : LOGD(" illegal fraction");
2661 0 : staff->log2Denom = 2;
2662 0 : staff->numerator = 4;
2663 : }
2664 :
2665 69 : staff->iLayout = readByte();
2666 69 : staff->topDistX = readInt();
2667 69 : staff->btmDistX = readInt();
2668 69 : staff->color = readColor();
2669 69 : readExtra();
2670 :
2671 : CAPELLA_TRACE(" Staff iLayout %d", staff->iLayout);
2672 : // Stimmen
2673 69 : unsigned nVoices = readUnsigned();
2674 138 : for (unsigned i = 0; i < nVoices; i++) {
2675 69 : readVoice(staff, i);
2676 : }
2677 69 : system->staves.append(staff);
2678 69 : }
2679 :
2680 : //---------------------------------------------------------
2681 : // readSystem
2682 : //---------------------------------------------------------
2683 :
2684 67 : void Capella::readSystem()
2685 : {
2686 67 : if (readChar() != 'S') {
2687 0 : throw Capella::Error::BAD_SYSTEM_SIG;
2688 : }
2689 :
2690 67 : CapSystem* s = new CapSystem;
2691 67 : s->nAddBarCount = readInt();
2692 67 : s->bBarCountReset = readByte();
2693 67 : s->explLeftIndent = readByte();
2694 :
2695 67 : s->beamMode = CapBeamMode(readByte());
2696 67 : s->tempo = readUnsigned();
2697 67 : s->color = readColor();
2698 67 : readExtra();
2699 :
2700 67 : unsigned char b = readByte();
2701 67 : s->bJustified = b & 2;
2702 67 : s->bPageBreak = (b & 4) != 0;
2703 67 : s->instrNotation = (b >> 3) & 7;
2704 :
2705 67 : unsigned nStaves = readUnsigned();
2706 136 : for (unsigned i = 0; i < nStaves; i++) {
2707 69 : readStaff(s);
2708 : }
2709 67 : systems.append(s);
2710 67 : }
2711 :
2712 : //---------------------------------------------------------
2713 : // toTicks
2714 : //---------------------------------------------------------
2715 :
2716 2047 : Fraction BasicDurationalObj::ticks() const
2717 : {
2718 2047 : if (noDuration) {
2719 0 : return Fraction(0, 1);
2720 : }
2721 2047 : Fraction len = { 0, 1 };
2722 2047 : switch (t) {
2723 25 : case TIMESTEP::D1: len = Fraction(1, 1);
2724 25 : break;
2725 14 : case TIMESTEP::D2: len = Fraction(1, 2);
2726 14 : break;
2727 687 : case TIMESTEP::D4: len = Fraction(1, 4);
2728 687 : break;
2729 760 : case TIMESTEP::D8: len = Fraction(1, 8);
2730 760 : break;
2731 561 : case TIMESTEP::D16: len = Fraction(1, 16);
2732 561 : break;
2733 0 : case TIMESTEP::D32: len = Fraction(1, 32);
2734 0 : break;
2735 0 : case TIMESTEP::D64: len = Fraction(1, 64);
2736 0 : break;
2737 0 : case TIMESTEP::D128: len = Fraction(1, 128);
2738 0 : break;
2739 0 : case TIMESTEP::D256: len = Fraction(1, 256);
2740 0 : break;
2741 0 : case TIMESTEP::D_BREVE: len = Fraction(2, 1);
2742 0 : break;
2743 0 : default:
2744 0 : LOGD("BasicDurationalObj::ticks: illegal duration value %d", int(t));
2745 0 : break;
2746 : }
2747 2047 : Fraction slen = len;
2748 2047 : int dots = nDots;
2749 2097 : while (dots--) {
2750 50 : slen /= Fraction(2, 1);
2751 50 : len += slen;
2752 : }
2753 2047 : return len;
2754 : }
2755 :
2756 : //---------------------------------------------------------
2757 : // readPoint
2758 : //---------------------------------------------------------
2759 :
2760 32 : QPointF Capella::readPoint()
2761 : {
2762 32 : int x = readInt();
2763 32 : int y = readInt();
2764 32 : return QPointF(double(x), double(y));
2765 : }
2766 :
2767 146 : CapStaffLayout* Capella::staffLayout(int idx)
2768 : {
2769 146 : if (idx < 0 || idx >= _staffLayouts.size()) {
2770 4 : return nullptr;
2771 : }
2772 142 : return _staffLayouts[idx];
2773 : }
2774 :
2775 : //---------------------------------------------------------
2776 : // read
2777 : //---------------------------------------------------------
2778 :
2779 21 : void Capella::read(QFile* fp)
2780 : {
2781 21 : f = fp;
2782 21 : curPos = 0;
2783 :
2784 : char signature[9];
2785 21 : read(signature, 8);
2786 21 : signature[8] = 0;
2787 21 : if (memcmp(signature, "cap3-v:", 7) != 0) {
2788 0 : throw Capella::Error::BAD_SIG;
2789 : }
2790 :
2791 : // CAPELLA_TRACE("read Capella file signature <%s>", signature);
2792 :
2793 : // TODO: test for signature[7] = a-z
2794 :
2795 21 : author = readString();
2796 19 : keywords = readString();
2797 19 : comment = readString();
2798 :
2799 : // CAPELLA_TRACE("author <%s> keywords <%s> comment <%s>", author, keywords, comment);
2800 :
2801 19 : nRel = readUnsigned(); // 75
2802 19 : nAbs = readUnsigned(); // 16
2803 19 : unsigned char b = readByte();
2804 19 : bUseRealSize = b & 1;
2805 19 : bAllowCompression = b & 2;
2806 19 : bPrintLandscape = b & 16;
2807 :
2808 : // CAPELLA_TRACE(" nRel %d nAbs %d useRealSize %d compression %d", nRel, nAbs, bUseRealSize, bAllowCompression);
2809 :
2810 19 : readLayout();
2811 :
2812 19 : beamRelMin0 = readByte(); // basic setup for beam slope
2813 19 : beamRelMin1 = readByte();
2814 19 : beamRelMax0 = readByte();
2815 19 : beamRelMax1 = readByte();
2816 :
2817 19 : readExtra();
2818 :
2819 19 : readDrawObjectArray(); // Galerie (gesammelte Grafikobjekte)
2820 :
2821 15 : unsigned n = readUnsigned();
2822 15 : if (n) {
2823 0 : LOGD("Gallery objects");
2824 : }
2825 15 : for (unsigned int i = 0; i < n; ++i) {
2826 : /*char* s =*/
2827 0 : readString(); // Namen der Galerie-Objekte
2828 : // CAPELLA_TRACE("Galerie: <%s>", s);
2829 : }
2830 :
2831 : // CAPELLA_TRACE("read backgroundChord");
2832 15 : backgroundChord = new ChordObj(this);
2833 15 : backgroundChord->read(); // contains graphic objects on the page background
2834 : // CAPELLA_TRACE("read backgroundChord done");
2835 15 : bShowBarCount = readByte(); // Taktnumerierung zeigen
2836 15 : barNumberFrame = readByte(); // 0=kein, 1=Rechteck, 2=Ellipse
2837 15 : nBarDistX = readByte();
2838 15 : nBarDistY = readByte();
2839 15 : QFont barNumFont = readFont();
2840 15 : nFirstPage = readUnsigned(); // Versatz fuer Seitenzaehlung
2841 15 : leftPageMargins = readUnsigned(); // Seitenraender
2842 15 : topPageMargins = readUnsigned();
2843 15 : rightPageMargins = readUnsigned();
2844 15 : btmPageMargins = readUnsigned();
2845 :
2846 15 : unsigned nSystems = readUnsigned();
2847 82 : for (unsigned i = 0; i < nSystems; i++) {
2848 67 : readSystem();
2849 : }
2850 : char esig[4];
2851 15 : read(esig, 4);
2852 15 : if (memcmp(esig, "\0\0\0\0", 4) != 0) {
2853 0 : throw Capella::Error::BAD_SIG;
2854 : }
2855 15 : }
2856 :
2857 : //---------------------------------------------------------
2858 : // importCapella
2859 : //---------------------------------------------------------
2860 :
2861 15 : Err importCapella(MasterScore* score, const QString& name)
2862 : {
2863 15 : QFile fp(name);
2864 15 : if (!fp.exists()) {
2865 0 : return Err::FileNotFound;
2866 : }
2867 15 : if (!fp.open(QIODevice::ReadOnly)) {
2868 0 : return Err::FileOpenError;
2869 : }
2870 :
2871 15 : Capella cf;
2872 : try {
2873 15 : cf.read(&fp);
2874 12 : fp.close();
2875 12 : convertCapella(score, &cf, false);
2876 : }
2877 5 : catch (Capella::Error errNo) {
2878 5 : if (!MScore::noGui) {
2879 0 : MessageBox(score->iocContext()).warning(muse::trc("iex_capella", "Import Capella"),
2880 0 : muse::qtrc("iex_capella", "Import failed: %1").arg(cf.error(errNo)).toStdString(),
2881 : { MessageBox::Ok });
2882 : }
2883 5 : fp.close();
2884 : // avoid another error message box
2885 5 : return Err::NoError;
2886 5 : }
2887 10 : return Err::NoError;
2888 15 : }
2889 : }
|