LCOV - code coverage report
Current view: top level - src/importexport/capella/internal - capella.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 57.2 % 1717 982
Test Date: 2026-11-05 04:07:02

            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              : }
        

Generated by: LCOV version 2.0-1