LCOV - code coverage report
Current view: top level - src/braille/internal - braille.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 63.6 % 1711 1089
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              : #include "braille.h"
      24              : 
      25              : #include <QRegularExpression>
      26              : 
      27              : #include "containers.h"
      28              : 
      29              : #include "engraving/dom/accidental.h"
      30              : #include "engraving/dom/arpeggio.h"
      31              : #include "engraving/dom/articulation.h"
      32              : #include "engraving/dom/barline.h"
      33              : #include "engraving/dom/breath.h"
      34              : #include "engraving/dom/chord.h"
      35              : #include "engraving/dom/clef.h"
      36              : #include "engraving/dom/durationtype.h"
      37              : #include "engraving/dom/dynamic.h"
      38              : #include "engraving/dom/engravingitem.h"
      39              : #include "engraving/dom/fermata.h"
      40              : #include "engraving/dom/fingering.h"
      41              : #include "engraving/dom/hairpin.h"
      42              : #include "engraving/dom/jump.h"
      43              : #include "engraving/dom/keysig.h"
      44              : #include "engraving/dom/lyrics.h"
      45              : #include "engraving/dom/marker.h"
      46              : #include "engraving/dom/measure.h"
      47              : #include "engraving/dom/mmrest.h"
      48              : #include "engraving/dom/mscore.h"
      49              : #include "engraving/dom/note.h"
      50              : #include "engraving/dom/page.h"
      51              : #include "engraving/dom/part.h"
      52              : #include "engraving/dom/pitchspelling.h"
      53              : #include "engraving/dom/rest.h"
      54              : #include "engraving/dom/score.h"
      55              : #include "engraving/dom/segment.h"
      56              : #include "engraving/dom/slur.h"
      57              : #include "engraving/dom/spanner.h"
      58              : #include "engraving/dom/staff.h"
      59              : #include "engraving/dom/system.h"
      60              : #include "engraving/dom/tempotext.h"
      61              : #include "engraving/dom/text.h"
      62              : #include "engraving/dom/tie.h"
      63              : #include "engraving/dom/timesig.h"
      64              : #include "engraving/dom/tuplet.h"
      65              : #include "engraving/dom/utils.h"
      66              : #include "engraving/dom/volta.h"
      67              : 
      68              : #include "louis.h"
      69              : #include "braillecode.h"
      70              : 
      71              : #define BRAILLE_TRACE_ENABLED 0
      72              : #if BRAILLE_TRACE_ENABLED
      73              : #define BRAILLE_TRACE LOGD
      74              : #else
      75              : #define BRAILLE_TRACE LOGN
      76              : #endif
      77              : 
      78              : namespace mu::engraving {
      79              : // Max lyrics num
      80              : #define MAX_LYRICS_NUM                  16
      81              : // Table 1. Page 2. Music Braille Code 2015.
      82              : #define BRAILLE_EQUALS_METRONOME        QString("7")
      83              : #define BRAILLE_MUSICAL_HYPEN           QString("\"")
      84              : #define BRAILLE_BARLINE                 QString(" ")
      85              : #define BRAILLE_BARLINE_BROKEN          QString("K")
      86              : #define BRAILLE_BARLINE_DOUBLE          QString("<K'")
      87              : #define BRAILLE_BARLINE_END             QString("<K")
      88              : #define BRAILLE_BARLINE_DOTTED          QString("l")
      89              : 
      90              : #define BRAILLE_ACC_NATURAL             QString("*")
      91              : #define BRAILLE_ACC_SHARP               QString("%")
      92              : #define BRAILLE_ACC_FLAT                QString("<")
      93              : #define BRAILLE_ACC_QUARTER_STEP        QString("@")
      94              : #define BRAILLE_ACC_3QUARTER_STEP       QString("_")
      95              : #define BRAILLE_ACC_5QUARTER_STEP       QString(".") //extrapolated from octave marks. not sure.
      96              : 
      97              : // Table 2. Page 4. Music Braille Code 2015
      98              : //8th and 128th notes have the same representation in Braille
      99              : #define BRAILLE_C_8TH_128TH             'D'
     100              : #define BRAILLE_D_8TH_128TH             'E'
     101              : #define BRAILLE_E_8TH_128TH             'F'
     102              : #define BRAILLE_F_8TH_128TH             'G'
     103              : #define BRAILLE_G_8TH_128TH             'H'
     104              : #define BRAILLE_A_8TH_128TH             'I'
     105              : #define BRAILLE_B_8TH_128TH             'J'
     106              : //64th and quarter notes have the same representation in Braille
     107              : #define BRAILLE_C_64TH_QUARTER          '?'
     108              : #define BRAILLE_D_64TH_QUARTER          ':'
     109              : #define BRAILLE_E_64TH_QUARTER          '$'
     110              : #define BRAILLE_F_64TH_QUARTER          ']'
     111              : #define BRAILLE_G_64TH_QUARTER          '\\'
     112              : #define BRAILLE_A_64TH_QUARTER          '['
     113              : #define BRAILLE_B_64TH_QUARTER          'W'
     114              : //32nd and half notes have the same representation in Braille
     115              : #define BRAILLE_C_32ND_HALF             'N'
     116              : #define BRAILLE_D_32ND_HALF             'o'
     117              : #define BRAILLE_E_32ND_HALF             'p'
     118              : #define BRAILLE_F_32ND_HALF             'q'
     119              : #define BRAILLE_G_32ND_HALF             'r'
     120              : #define BRAILLE_A_32ND_HALF             's'
     121              : #define BRAILLE_B_32ND_HALF             't'
     122              : //16th and whole notes have the same representation in Braille.
     123              : // Breve has the same representation, but with an extra suffix;
     124              : // 256th has the same representation, but with an extra prefix;
     125              : #define BRAILLE_C_16TH_WHOLE            'Y'
     126              : #define BRAILLE_D_16TH_WHOLE            'Z'
     127              : #define BRAILLE_E_16TH_WHOLE            '&'
     128              : #define BRAILLE_F_16TH_WHOLE            '='
     129              : #define BRAILLE_G_16TH_WHOLE            '('
     130              : #define BRAILLE_A_16TH_WHOLE            '!'
     131              : #define BRAILLE_B_16TH_WHOLE            ')'
     132              : 
     133              : #define BRAILLE_BREVE_SUFFIX            QString("k")
     134              : #define BRAILLE_256TH_PREFIX            QString(";<1")
     135              : #define BRAILLE_DURATION_DOT            QString("'")
     136              : 
     137              : // Table 3. Page 4. Music Braille Code 2015.
     138              : #define BRAILLE_BELOW_FIRST_OCTAVE      QString("@@")
     139              : #define BRAILLE_1ST_OCTAVE              QString("@")
     140              : #define BRAILLE_2ND_OCTAVE              QString("^")
     141              : #define BRAILLE_3RD_OCTAVE              QString("_")
     142              : #define BRAILLE_4TH_OCTAVE              QString("\"")
     143              : #define BRAILLE_5TH_OCTAVE              QString(".")
     144              : #define BRAILLE_6TH_OCTAVE              QString(";")
     145              : #define BRAILLE_7TH_OCTAVE              QString(",")
     146              : #define BRAILLE_ABOVE_7TH_OCTAVE        QString(",,")
     147              : 
     148              : // Table 4. Page 4. Music Braille Code 2015.
     149              : #define BRAILLE_TREBLE_CLEF             QString(">/l")
     150              : #define BRAILLE_TREBLE_CLEF_15MB        QString(">/l#15")
     151              : #define BRAILLE_TREBLE_CLEF_8VB         QString(">/l#8")
     152              : #define BRAILLE_TREBLE_CLEF_8VA         QString(">/l#h")
     153              : #define BRAILLE_TREBLE_CLEF_15MA        QString(">/l#ae")
     154              : #define BRAILLE_D_TREBLE_CLEF_8VB_O     QString(">/l/l#8")
     155              : #define BRAILLE_TREBLE_CLEF_8VB_P       QString(">/l#787")
     156              : #define BRAILLE_FRENCH_VIOLINE_CLEF     QString(">/@l")
     157              : #define BRAILLE_SOPRANO_CLEF            QString(">+@l")
     158              : #define BRAILLE_MEZZO_SOPRANO_CLEF      QString(">+^l")
     159              : #define BRAILLE_ALTO_CLEF               QString(">+l")
     160              : #define BRAILLE_TENOR_CLEF              QString(">+\"l")
     161              : #define BRAILLE_BARITONE_C_CLEF         QString(">+.l")
     162              : #define BRAILLE_BASS_CLEF               QString(">#l")
     163              : #define BRAILLE_BASS_CLEF_15MB          QString(">#l#15")
     164              : #define BRAILLE_BASS_CLEF_8VB           QString(">#l#8")
     165              : #define BRAILLE_BASS_CLEF_8VA           QString(">#l#h")
     166              : #define BRAILLE_BASS_CLEF_15MA          QString(">#l#ae")
     167              : #define BRAILLE_BARITONE_F_CLEF         QString(">#_l")
     168              : #define BRAILLE_SUBBASS_CLEF            QString(">#.l")
     169              : 
     170              : // Table 5. Page 5. Music Braille Code 2015.
     171              : #define BRAILLE_REST_LONG               QString("m^c^cm")
     172              : #define BRAILLE_REST_BREVE              QString("mk")
     173              : #define BRAILLE_REST_WHOLE              QString("m")
     174              : #define BRAILLE_REST_HALF               QString("u")
     175              : #define BRAILLE_REST_QUARTER            QString("v")
     176              : #define BRAILLE_REST_EIGHTH             QString("x")
     177              : #define BRAILLE_REST_16TH               QString("m")
     178              : #define BRAILLE_REST_32ND               QString("u")
     179              : #define BRAILLE_REST_64TH               QString("v")
     180              : #define BRAILLE_REST_128TH              QString("x")
     181              : #define BRAILLE_REST_256TH              QString(";<1m")
     182              : #define BRAILLE_REST_MEASURE            QString("m")
     183              : 
     184              : // Table 9. Page 7. Music Braille Code 2015.
     185              : #define BRAILLE_OCTAVE                  QString("-")
     186              : #define BRAILLE_SECOND                  QString("/")
     187              : #define BRAILLE_THIRD                   QString("+")
     188              : #define BRAILLE_FOURTH                  QString("#")
     189              : #define BRAILLE_FIFTH                   QString("9")
     190              : #define BRAILLE_SIXTH                   QString("0")
     191              : #define BRAILLE_SEVENTH                 QString("3")
     192              : 
     193              : // Table 10. Page 7. Music Braille Code 2015
     194              : #define BRAILLE_TIE                     QString("@c")
     195              : #define BRAILLE_TIE_CHORD               QString(".c")
     196              : 
     197              : // Table 11. Page 8. Music Braille Code 2015
     198              : #define BRAILLE_FULL_MEASURE_IN_ACORD   QString("<>")
     199              : #define BRAILLE_PART_MEASURE_IN_ACORD   QString("\"1")
     200              : #define BRAILLE_MEASURE_DIVISION        QString(".k")
     201              : 
     202              : // Table 13. Page 9. Music Braille Code 2015.
     203              : #define BRAILLE_SLUR_SHORT              QString("c")
     204              : #define BRAILLE_SLUR_SHORT_CONVERGENCE  QString(",c")
     205              : #define BRAILLE_SLUR_BRACKET_START      QString(";b")
     206              : #define BRAILLE_SLUR_BRACKET_END        QString("^2")
     207              : 
     208              : // Table 14. Page 10. Music Braille Code 2015
     209              : #define BRAILLE_TREMOLO_8THS            QString("^b")
     210              : #define BRAILLE_TREMOLO_16THS           QString("^l")
     211              : #define BRAILLE_TREMOLO_32NDS           QString("^1")
     212              : #define BRAILLE_TREMOLO_64THS           QString("^k")
     213              : #define BRAILLE_TREMOLO_128THS          QString("^'")
     214              : #define BRAILLE_TREMOLO_8THS_ALT        QString(".b")
     215              : #define BRAILLE_TREMOLO_16THS_ALT       QString(".l")
     216              : #define BRAILLE_TREMOLO_32NDS_ALT       QString(".1")
     217              : #define BRAILLE_TREMOLO_64THS_ALT       QString(".k")
     218              : #define BRAILLE_TREMOLO_128THS_ALT      QString(".'")
     219              : 
     220              : // Table 15. Page 11. Music Braille Code 2015.
     221              : #define BRAILLE_FINGERING_OPEN          QString("K")
     222              : #define BRAILLE_FINGERING_1ST           QString("a")
     223              : #define BRAILLE_FINGERING_2ND           QString("b")
     224              : #define BRAILLE_FINGERING_3RD           QString("l")
     225              : #define BRAILLE_FINGERING_4TH           QString("1")
     226              : #define BRAILLE_FINGERING_5TH           QString("k")
     227              : #define BRAILLE_FINGERING_CHANGE        QString("c")
     228              : 
     229              : // Table 16.A. Page 12. Music Braille Code 2015.
     230              : #define BRAILLE_GRACE_LONG              QString("\"5")
     231              : #define BRAILLE_GRACE_SHORT             QString("5")
     232              : 
     233              : // Table 16.B. Page 12. Music Braille Code 2015.
     234              : #define BRAILLE_TRILL                   QString("6")
     235              : #define BRAILLE_TRILL_FLAT              QString("<6")
     236              : #define BRAILLE_TRILL_SHARP             QString("%6")
     237              : #define BRAILLE_TURN_BTWN_NOTES         QString("4")
     238              : #define BRAILLE_TURN_NOTE               QString(",4")
     239              : #define BRAILLE_INVERTED_TURN_BTWN_NOTES QString("4l")
     240              : #define BRAILLE_INVERTED_TURN_NOTE      QString(",4l")
     241              : 
     242              : // Table 16.C. Page 13. Music Braille Code 2015
     243              : #define BRAILLE_SHORT_TRILL             QString("\"6")
     244              : #define BRAILLE_TREBLEMENT              QString(";6")
     245              : #define BRAILLE_MORDENT                 QString("\"6l")
     246              : #define BRAILLE_PRALL_MORDENT           QString(";6l")
     247              : 
     248              : // Table 16.D. Page 13. Music Braille Code 2015
     249              : #define BRAILLE_GLISSANDO               QString("@a")
     250              : 
     251              : // Table 16.F. Page 14. Music Braille Code 2015
     252              : #define BRAILLE_MORDENT_WITH_UPPER_FIX  QString("4;6")
     253              : #define BRAILLE_UP_PRALL                QString("4l;6")
     254              : #define BRAILLE_UP_MORDENT              QString("4l;6l") //extrapolated. not sure
     255              : #define BRAILLE_DOWN_MORDENT            QString("4;6")  //extrapolated. not sure
     256              : #define BRAILLE_PRALL_DOWN              QString(";64l")  //extrapolated. not sure
     257              : #define BRAILLE_PRALL_UP                QString(";64")   //extrapolated. not sure
     258              : #define BRAILLE_LINE_PRALL              QString(";6l4")  //extrapolated. not sure
     259              : 
     260              : // Table 17. Page 15.x Music Braille Code 2015
     261              : #define BRAILLE_BARLINE_START_REPEAT    QString("<7")
     262              : #define BRAILLE_BARLINE_END_REPEAT      QString("<2")
     263              : 
     264              : // Table 18. Page 15. Music Braille Code 2015
     265              : #define BRAILLE_MEASURE_REPEAT          QString("7")
     266              : 
     267              : // Table 20. Page 16. Music Braille Code 2015
     268              : #define BRAILLE_SEGNO                   QString("+ ")
     269              : #define BRAILLE_CODA                    QString("+l ")
     270              : #define BRAILLE_FINE                    QString(">fine> ")
     271              : #define BRAILLE_TOCODA                  QString(">to coda> ")
     272              : #define BRAILLE_DA_CAPO                 QString(">d'c'> ")
     273              : #define BRAILLE_DA_CAPO_AL_FINE         QString(">d'c' al fine> ")
     274              : #define BRAILLE_DA_CAPO_AL_CODA         QString(">d'c' al coda> ")
     275              : #define BRAILLE_DAL_SEGNO_AL_CODA       QString(">d's' al coda> ")
     276              : #define BRAILLE_DAL_SEGNO_AL_FINE       QString(">d's' al fine> ")
     277              : #define BRAILLE_DAL_SEGNO               QString(">d's'> ")
     278              : 
     279              : // Table 21. Page 16. Music Braille Code 2015
     280              : #define BRAILLE_MUSIC_PARENTHESES       QString(",'")
     281              : 
     282              : // Table 22. Page 17. Music Braille Code 2015.
     283              : #define BRAILLE_ARPEGGIO_UPWARD         QString(">k")
     284              : #define BRAILLE_ARPEGGIO_DOWNWARD       QString(">kk")
     285              : #define BRAILLE_ARPEGGIO_MULTISTAVES    QString("\"")
     286              : 
     287              : // Table 22.A. Page 17. Music Braille Code 2015.
     288              : #define BRAILLE_ARTIC_STACCATO          QString("8")
     289              : #define BRAILLE_ARTIC_STACCATISSIMO     QString(",8")
     290              : #define BRAILLE_ARTIC_TENUTO_STACCATO   QString("\"8")
     291              : #define BRAILLE_ARTIC_TENUTO            QString("_8")
     292              : #define BRAILLE_ARTIC_ACCENT            QString(".8")
     293              : #define BRAILLE_ARTIC_MARCATO           QString(";8")
     294              : #define BRAILLE_ARTIC_REVERSED_ACCENT   QString("@8")
     295              : #define BRAILLE_ARTIC_EXPRESSIVE_ACCENT QString("^8")
     296              : #define BRAILLE_ARTIC_SWELL             QString("*'")
     297              : 
     298              : // Table 22.2.B. Page 18. Music Braille Code 2015.
     299              : #define BRAILLE_FERMATA                 QString("<l")
     300              : #define BRAILLE_SHORT_FERMATA           QString("^<l")
     301              : #define BRAILLE_LONG_FERMATA            QString(";<l")
     302              : #define BRAILLE_BREATH                  QString(">1")
     303              : #define BRAILLE_CAESURA                 QString(",/")
     304              : 
     305              : // Table 22.C
     306              : #define BRAILLE_HAIRPIN_DIV_START       QString(">c")
     307              : #define BRAILLE_HAIRPIN_DIV_END         QString(">3")
     308              : #define BRAILLE_HAIRPIN_CONV_START      QString(">d")
     309              : #define BRAILLE_HAIRPIN_CONV_END        QString(">4")
     310              : #define BRAILLE_CRESC                   QString(">cr'")
     311              : #define BRAILLE_DESCRESC                QString(">decr'")
     312              : #define BRAILLE_DIM                     QString(">dim'")
     313              : #define BRAILLE_LV                      QString(">lvb'")
     314              : #define BRAILLE_LINE_CONT_START_1       QString("''")
     315              : #define BRAILLE_LINE_CONT_END_1         QString(">'")
     316              : #define BRAILLE_LINE_CONT_START_2       QString("--")
     317              : #define BRAILLE_LINE_CONT_END_2         QString(">-")
     318              : 
     319              : // TABLE 24.B. Page 22. Music Braille Code 2015
     320              : #define BRAILLE_DOWN_BOW                QString("<b")
     321              : #define BRAILLE_UP_BOW                  QString("<'")
     322              : #define BRAILLE_LEFT_HAND_PIZZICATO     QString("_>")
     323              : 
     324            0 : BrailleEngravingItem::BrailleEngravingItem(BEIType type,
     325              :                                            EngravingItem* el,
     326            0 :                                            QString braille)
     327              : {
     328            0 :     m_type = type;
     329            0 :     m_el = el;
     330            0 :     m_braille = braille;
     331            0 :     if (type == BEIType::EndOfLine) {
     332            0 :         m_start = -1;
     333            0 :         m_end = -1;
     334              :     } else {
     335            0 :         m_start = 0;
     336            0 :         m_end = braille.length();
     337              :     }
     338            0 : }
     339              : 
     340            0 : BrailleEngravingItem::BrailleEngravingItem(BEIType type,
     341              :                                            EngravingItem* e, QString b,
     342            0 :                                            QString extra_info, int extra_val)
     343            0 :     : BrailleEngravingItem(type, e, b)
     344              : {
     345            0 :     m_extra_info = extra_info;
     346            0 :     m_extra_val = extra_val;
     347            0 : }
     348              : 
     349            0 : BrailleEngravingItem::~BrailleEngravingItem()
     350              : {
     351            0 :     m_braille = QString();
     352            0 :     m_extra_info = QString();
     353            0 : }
     354              : 
     355            0 : BEIType BrailleEngravingItem::type()
     356              : {
     357            0 :     return m_type;
     358              : }
     359              : 
     360            0 : EngravingItem* BrailleEngravingItem::el()
     361              : {
     362            0 :     return m_el;
     363              : }
     364              : 
     365            0 : QString BrailleEngravingItem::braille()
     366              : {
     367            0 :     return m_braille;
     368              : }
     369              : 
     370            0 : int BrailleEngravingItem::start()
     371              : {
     372            0 :     return m_start;
     373              : }
     374              : 
     375            0 : int BrailleEngravingItem::end()
     376              : {
     377            0 :     return m_end;
     378              : }
     379              : 
     380            0 : QString BrailleEngravingItem::extra_info()
     381              : {
     382            0 :     return m_extra_info;
     383              : }
     384              : 
     385            0 : int BrailleEngravingItem::extra_val()
     386              : {
     387            0 :     return m_extra_val;
     388              : }
     389              : 
     390            0 : void BrailleEngravingItem::setBraille(QString b)
     391              : {
     392            0 :     m_braille = b;
     393            0 : }
     394              : 
     395            0 : void BrailleEngravingItem::setPos(int start, int end)
     396              : {
     397            0 :     m_start = start;
     398            0 :     m_end = end;
     399            0 : }
     400              : 
     401            0 : void BrailleEngravingItem::setExtra(QString info, int val)
     402              : {
     403            0 :     m_extra_info = info;
     404            0 :     m_extra_val = val;
     405            0 : }
     406              : 
     407            0 : BrailleEngravingItemList::BrailleEngravingItemList()
     408              : {
     409            0 :     m_braille_str = QString();
     410            0 : }
     411              : 
     412            0 : BrailleEngravingItemList::~BrailleEngravingItemList()
     413              : {
     414            0 :     clear();
     415            0 : }
     416              : 
     417            0 : void BrailleEngravingItemList::clear()
     418              : {
     419            0 :     m_braille_str = QString();
     420            0 :     m_items.clear();
     421            0 : }
     422              : 
     423            0 : void BrailleEngravingItemList::join(BrailleEngravingItemList* another, bool newline, bool del)
     424              : {
     425            0 :     int len = m_braille_str.length();
     426              : 
     427            0 :     if (newline && !m_braille_str.isEmpty()) {
     428            0 :         BrailleEngravingItem item = BrailleEngravingItem(BEIType::EndOfLine, NULL, "\n");
     429            0 :         m_items.push_back(item);
     430            0 :         m_braille_str.append("\n");
     431            0 :         len++;
     432            0 :     }
     433              : 
     434            0 :     m_braille_str.append(another->brailleStr());
     435              : 
     436            0 :     for (auto item: *another->items()) {
     437            0 :         int start = item.start() + len;
     438            0 :         int end = item.end() + len;
     439            0 :         item.setPos(start, end);
     440            0 :         m_items.push_back(item);
     441            0 :     }
     442              : 
     443            0 :     if (del) {
     444            0 :         delete another;
     445              :     }
     446            0 : }
     447              : 
     448            0 : void BrailleEngravingItemList::join(std::vector<BrailleEngravingItemList*> lst, bool newline, bool del)
     449              : {
     450            0 :     for (auto item: lst) {
     451            0 :         join(item, newline, del);
     452              :     }
     453            0 : }
     454              : 
     455            0 : QString BrailleEngravingItemList::brailleStr()
     456              : {
     457            0 :     return m_braille_str;
     458              : }
     459              : 
     460            0 : std::vector<BrailleEngravingItem>* BrailleEngravingItemList::items()
     461              : {
     462            0 :     return &m_items;
     463              : }
     464              : 
     465            0 : void BrailleEngravingItemList::setBrailleStr(QString str)
     466              : {
     467            0 :     m_braille_str = str;
     468            0 :     m_items.clear();
     469            0 : }
     470              : 
     471            0 : void BrailleEngravingItemList::insert(int pos, BrailleEngravingItem bei)
     472              : {
     473            0 :     if (bei.braille().isEmpty()) {
     474            0 :         return;
     475              :     }
     476              : 
     477            0 :     if (pos == 0) { // insert front
     478            0 :         QString buff = bei.braille();
     479            0 :         int len = bei.braille().length();
     480              : 
     481            0 :         for (size_t i=0; i < m_items.size(); i++) {
     482            0 :             int start = m_items[i].start() + len;
     483            0 :             int end = m_items[i].end() + len;
     484            0 :             m_items[i].setPos(start, end);
     485              :         }
     486              : 
     487            0 :         bei.setPos(0, len);
     488            0 :         m_items.insert(m_items.begin(), bei);
     489            0 :         m_braille_str = buff.append(m_braille_str);
     490            0 :     } else if (pos >= m_braille_str.length()) { // insert back
     491            0 :         int len = bei.braille().length();
     492              : 
     493            0 :         int start = m_braille_str.length();
     494            0 :         int end = start + len - 1;
     495            0 :         bei.setPos(start, end);
     496            0 :         m_items.push_back(bei);
     497              : 
     498            0 :         m_braille_str.append(bei.braille());
     499              :     } else { // insert middle
     500            0 :         std::vector<BrailleEngravingItem> lst;
     501            0 :         QString buff = "";
     502              : 
     503            0 :         std::vector<BrailleEngravingItem>::iterator ptr;
     504            0 :         int inc = 0;
     505            0 :         for (ptr = m_items.begin(); ptr < m_items.end(); ptr++) {
     506            0 :             if (ptr->start() >= pos) {
     507            0 :                 if (inc == 0) {
     508            0 :                     if (bei.type() != BEIType::EndOfLine) {
     509            0 :                         inc = bei.braille().length();
     510            0 :                         int start = buff.length();
     511            0 :                         int end = start + inc - 1;
     512            0 :                         bei.setPos(start, end);
     513              :                     }
     514            0 :                     lst.push_back(bei);
     515              :                 }
     516            0 :                 if (ptr->type() != BEIType::EndOfLine) {
     517            0 :                     int start = ptr->start() + inc;
     518            0 :                     int end = ptr->end() + inc;
     519            0 :                     ptr->setPos(start, end);
     520              :                 }
     521            0 :                 lst.push_back(*ptr);
     522              :             } else {
     523            0 :                 lst.push_back(*ptr);
     524              :             }
     525            0 :             buff.append(bei.braille());
     526              :         }
     527              : 
     528            0 :         m_braille_str = buff;
     529            0 :         m_items = lst;
     530            0 :     }
     531              : }
     532              : 
     533            0 : bool BrailleEngravingItemList::isEmpty()
     534              : {
     535            0 :     return m_braille_str.isEmpty();
     536              : }
     537              : 
     538            0 : void BrailleEngravingItemList::addEngravingItem(EngravingItem* el, const QString& braille)
     539              : {
     540              :     //braille = braille.replace(QRegularExpression ("/\\/"), "\\\\");
     541              :     //Manual doubling slashes '\' because Regex doesn't work. Don't know why.
     542            0 :     QString txt = QString();
     543            0 :     for (int i=0; i < braille.length(); i++) {
     544            0 :         if (braille.at(i) == '\\') {
     545            0 :             txt.append(braille.at(i));
     546              :         }
     547            0 :         txt.append(braille.at(i));
     548              :     }
     549            0 :     QString unitxt = QString::fromStdString(braille_long_translate(table_ascii_to_unicode.c_str(), txt.toStdString()));
     550              : 
     551            0 :     BrailleEngravingItem bei = BrailleEngravingItem(BEIType::EngravingItem, el, unitxt);
     552            0 :     bei.setExtra(el->typeName(), -1);
     553            0 :     insert(MAX_LIVE_BRAILLE_LENGTH, bei);
     554            0 : }
     555              : 
     556            0 : void BrailleEngravingItemList::addLyricsItem(Lyrics* l)
     557              : {
     558            0 :     std::string txt = l->plainText().toStdString();
     559            0 :     QString unitxt = QString::fromStdString(braille_long_translate(table_for_literature.c_str(), txt));
     560              : 
     561            0 :     switch (l->syllabic()) {
     562            0 :     case LyricsSyllabic::SINGLE:
     563              :     case LyricsSyllabic::BEGIN:
     564              :     {
     565            0 :         if (!m_braille_str.isEmpty()) {
     566            0 :             m_braille_str.append(" ");
     567              :         }
     568              :     }
     569              :     // fallthrough
     570              :     case LyricsSyllabic::END:
     571              :     case LyricsSyllabic::MIDDLE:
     572              :     {
     573            0 :         BrailleEngravingItem bei = BrailleEngravingItem(BEIType::LyricItem, l, unitxt, QString::fromStdString(txt), -1);
     574            0 :         insert(MAX_LIVE_BRAILLE_LENGTH, bei);
     575            0 :         break;
     576            0 :     }
     577              :     }
     578            0 : }
     579              : 
     580            0 : BrailleEngravingItem* BrailleEngravingItemList::getItem(int pos)
     581              : {
     582            0 :     for (size_t i=0; i < m_items.size(); i++) {
     583            0 :         if (m_items[i].start() <= pos && m_items[i].end() >= pos) {
     584            0 :             return &m_items[i];
     585              :         }
     586              :     }
     587            0 :     return nullptr;
     588              : }
     589              : 
     590            0 : BrailleEngravingItem* BrailleEngravingItemList::getItem(engraving::EngravingItem* e)
     591              : {
     592            0 :     for (size_t i=0; i < m_items.size(); i++) {
     593            0 :         if (!m_items[i].el()) {
     594            0 :             continue;
     595              :         }
     596            0 :         if (m_items[i].el() == e) {
     597            0 :             return &m_items[i];
     598              :         }
     599            0 :         if (m_items[i].el()->elementBase() == e->elementBase()) {
     600            0 :             return &m_items[i];
     601              :         }
     602              :     }
     603            0 :     return nullptr;
     604              : }
     605              : 
     606            0 : void BrailleEngravingItemList::log()
     607              : {
     608            0 :     LOGD() << brailleStr();
     609            0 :     for (size_t i=0; i < m_items.size(); i++) {
     610            0 :         if (!m_items[i].el()) {
     611            0 :             LOGD() << " - null {" << m_items[i].start() << "," << m_items[i].end() << "}";
     612              :         } else {
     613            0 :             LOGD() << " -" << m_items[i].el()->accessibleInfo() << " {" << m_items[i].start() << "," << m_items[i].end() << "}";
     614              :         }
     615              :     }
     616            0 : }
     617              : 
     618          320 : TextToUEBBraille::TextToUEBBraille()
     619              : {
     620          320 :     textToBrailleASCII["a"] = 'a';
     621          320 :     textToBrailleASCII["b"] = 'b';
     622          320 :     textToBrailleASCII["c"] = 'c';
     623          320 :     textToBrailleASCII["d"] = 'd';
     624          320 :     textToBrailleASCII["e"] = 'e';
     625          320 :     textToBrailleASCII["f"] = 'f';
     626          320 :     textToBrailleASCII["g"] = 'g';
     627          320 :     textToBrailleASCII["h"] = 'h';
     628          320 :     textToBrailleASCII["i"] = 'i';
     629          320 :     textToBrailleASCII["j"] = 'j';
     630          320 :     textToBrailleASCII["k"] = 'k';
     631          320 :     textToBrailleASCII["l"] = 'l';
     632          320 :     textToBrailleASCII["m"] = 'm';
     633          320 :     textToBrailleASCII["n"] = 'n';
     634          320 :     textToBrailleASCII["o"] = 'o';
     635          320 :     textToBrailleASCII["p"] = 'p';
     636          320 :     textToBrailleASCII["q"] = 'q';
     637          320 :     textToBrailleASCII["r"] = 'r';
     638          320 :     textToBrailleASCII["s"] = 's';
     639          320 :     textToBrailleASCII["t"] = 't';
     640          320 :     textToBrailleASCII["u"] = 'u';
     641          320 :     textToBrailleASCII["v"] = 'v';
     642          320 :     textToBrailleASCII["w"] = 'w';
     643          320 :     textToBrailleASCII["x"] = 'x';
     644          320 :     textToBrailleASCII["y"] = 'y';
     645          320 :     textToBrailleASCII["z"] = 'z';
     646              : 
     647          320 :     textToBrailleASCII["A"] = 'a';
     648          320 :     textToBrailleASCII["B"] = 'b';
     649          320 :     textToBrailleASCII["C"] = 'c';
     650          320 :     textToBrailleASCII["D"] = 'd';
     651          320 :     textToBrailleASCII["E"] = 'e';
     652          320 :     textToBrailleASCII["F"] = 'f';
     653          320 :     textToBrailleASCII["G"] = 'g';
     654          320 :     textToBrailleASCII["H"] = 'h';
     655          320 :     textToBrailleASCII["I"] = 'i';
     656          320 :     textToBrailleASCII["J"] = 'j';
     657          320 :     textToBrailleASCII["K"] = 'k';
     658          320 :     textToBrailleASCII["L"] = 'l';
     659          320 :     textToBrailleASCII["M"] = 'm';
     660          320 :     textToBrailleASCII["N"] = 'n';
     661          320 :     textToBrailleASCII["O"] = 'o';
     662          320 :     textToBrailleASCII["P"] = 'p';
     663          320 :     textToBrailleASCII["Q"] = 'q';
     664          320 :     textToBrailleASCII["R"] = 'r';
     665          320 :     textToBrailleASCII["S"] = 's';
     666          320 :     textToBrailleASCII["T"] = 't';
     667          320 :     textToBrailleASCII["U"] = 'u';
     668          320 :     textToBrailleASCII["V"] = 'v';
     669          320 :     textToBrailleASCII["W"] = 'w';
     670          320 :     textToBrailleASCII["X"] = 'x';
     671          320 :     textToBrailleASCII["Y"] = 'y';
     672          320 :     textToBrailleASCII["Z"] = 'z';
     673              : 
     674          320 :     textToBrailleASCII["1"] = 'a';
     675          320 :     textToBrailleASCII["2"] = 'b';
     676          320 :     textToBrailleASCII["3"] = 'c';
     677          320 :     textToBrailleASCII["4"] = 'd';
     678          320 :     textToBrailleASCII["5"] = 'e';
     679          320 :     textToBrailleASCII["6"] = 'f';
     680          320 :     textToBrailleASCII["7"] = 'g';
     681          320 :     textToBrailleASCII["8"] = 'h';
     682          320 :     textToBrailleASCII["9"] = 'i';
     683          320 :     textToBrailleASCII["0"] = 'j';
     684              : 
     685          320 :     textToBrailleASCII[" "] = ' ';
     686          320 :     textToBrailleASCII[","] = '1';
     687          320 :     textToBrailleASCII[";"] = '2';
     688          320 :     textToBrailleASCII[":"] = '3';
     689          320 :     textToBrailleASCII["."] = '4';
     690          320 :     textToBrailleASCII["!"] = '6';
     691          320 :     textToBrailleASCII["("] = '7';
     692          320 :     textToBrailleASCII[")"] = '7';
     693          320 :     textToBrailleASCII["?"] = '8';
     694          320 :     textToBrailleASCII["="] = "\"7";
     695          320 :     textToBrailleASCII["\n"] = '\n';
     696          320 :     textToBrailleASCII["©"] = "~c";
     697          320 :     textToBrailleASCII["-"] = "-";
     698          320 :     textToBrailleASCII["*"] = "99";
     699              : 
     700              :     // Appendix B: Foreign language signs. Page 31.
     701              :     // https://www.ukaaf.org/wp-content/uploads/B017-Braille-Music-and-Unified-English-Braille.pdf
     702          320 :     textToBrailleASCII["ç"] = "&";
     703          320 :     textToBrailleASCII["é"] = "=";
     704          320 :     textToBrailleASCII["à"] = "(";
     705          320 :     textToBrailleASCII["è"] = "!";
     706          320 :     textToBrailleASCII["ù"] = ")";
     707          320 :     textToBrailleASCII["â"] = "*";
     708          320 :     textToBrailleASCII["ê"] = "<";
     709          320 :     textToBrailleASCII["î"] = "%";
     710          320 :     textToBrailleASCII["ô"] = "?";
     711          320 :     textToBrailleASCII["û"] = ":";
     712          320 :     textToBrailleASCII["ë"] = "$";
     713          320 :     textToBrailleASCII["ï"] = "]";
     714          320 :     textToBrailleASCII["ü"] = "\\";
     715          320 :     textToBrailleASCII["œ"] = "[";
     716          320 :     textToBrailleASCII["ß"] = "!";
     717          320 :     textToBrailleASCII["ö"] = "[";
     718          320 :     textToBrailleASCII["ä"] = ">";
     719          320 :     textToBrailleASCII["ì"] = "/";
     720          320 :     textToBrailleASCII["ò"] = "+";
     721          320 :     textToBrailleASCII["á"] = "(";
     722          320 :     textToBrailleASCII["ú"] = ")";
     723          320 :     textToBrailleASCII["ñ"] = "]";
     724          320 :     textToBrailleASCII["í"] = "/";
     725          320 :     textToBrailleASCII["ó"] = "+";
     726              : 
     727              :     // dynamics symbols
     728          320 :     textToBrailleASCII[QChar(0xE520)] = "p";
     729          320 :     textToBrailleASCII[QChar(0xE521)] = "m";
     730          320 :     textToBrailleASCII[QChar(0xE522)] = "f";
     731          320 :     textToBrailleASCII[QChar(0xE523)] = "r";
     732          320 :     textToBrailleASCII[QChar(0xE524)] = "s";
     733          320 :     textToBrailleASCII[QChar(0xE525)] = "z";
     734          320 :     textToBrailleASCII[QChar(0xE526)] = "n";
     735          320 : }
     736              : 
     737         3688 : QString TextToUEBBraille::braille(QChar c)
     738              : {
     739         3688 :     if (textToBrailleASCII[c] != nullptr) {
     740         3686 :         return QString(textToBrailleASCII[c]);
     741              :     }
     742            2 :     return QString(c);
     743              : }
     744              : 
     745          320 : QString TextToUEBBraille::braille(const QString& text)
     746              : {
     747          320 :     QString buffer, t, p;
     748          320 :     QTextStream rez(&buffer), tmp(&t);
     749          320 :     QChar prev;
     750              : 
     751         4008 :     for (QChar c : text) {
     752         3688 :         if (prev.isNumber() && c.isLetter()) {
     753            0 :             rez << ASCII_END_OF_NUMBER;
     754              :         }
     755              : 
     756         3688 :         if (prev.isLetter() && prev.isUpper() && (!c.isLetter() || (c.isLetter() && c.isLower()))) {
     757          341 :             tmp.flush();
     758          341 :             rez << p << t;
     759          341 :             t.clear();
     760          341 :             p.clear();
     761              :         }
     762              : 
     763         3688 :         if (c.isLetter()) {
     764         2651 :             if (c.isUpper()) {
     765          357 :                 if (prev.isUpper()) {
     766           16 :                     p = ASCII_PREFIX_CAPITAL_WORD;
     767              :                 } else {
     768          341 :                     p = ASCII_PREFIX_CAPITAL_LETTER;
     769              :                 }
     770          357 :                 tmp << braille(c);
     771              :             } else {
     772         2294 :                 rez << braille(c);
     773              :             }
     774         1037 :         } else if (c.isNumber()) {
     775          542 :             if (!prev.isNumber()) {
     776          356 :                 rez << ASCII_PREFIX_NUMBER;
     777              :             }
     778          542 :             rez << braille(c);
     779              :         } else {
     780          495 :             rez << braille(c);
     781              :         }
     782         3688 :         prev = c;
     783              :     }
     784              : 
     785          320 :     tmp.flush();
     786          320 :     rez << p << t;
     787          320 :     t.clear();
     788          320 :     p.clear();
     789              : 
     790          640 :     return rez.readAll();
     791          320 : }
     792              : 
     793           54 : Braille::Braille(Score* s)
     794              : {
     795           54 :     m_score = s;
     796          112 :     for (size_t i = 0; i < m_score->staves().size(); ++i) {
     797           58 :         m_context.previousNote.push_back(nullptr);
     798           58 :         m_context.currentClefType.push_back(ClefType::INVALID);
     799           58 :         m_context.currentKey.push_back(Key::INVALID);
     800              :     }
     801           54 : }
     802              : 
     803           54 : bool Braille::write(QIODevice& device)
     804              : {
     805           54 :     credits(device);
     806           54 :     instruments(device);
     807           54 :     size_t nrStaves = m_score->staves().size();
     808          108 :     std::vector<QString> measureBraille(nrStaves);
     809          108 :     std::vector<QString> line(nrStaves + 1);
     810           54 :     std::vector<QString> lyrics(nrStaves + 1);
     811           54 :     int currentLineLength = 0;
     812           54 :     int currentMeasureMaxLength = 0;
     813           54 :     bool measureAboveMax = false;
     814              : 
     815          354 :     for (MeasureBase* mb = m_score->measures()->first(); mb != nullptr; mb = mb->next()) {
     816          300 :         if (!mb->isMeasure()) {
     817           54 :             continue;
     818              :         }
     819          246 :         currentMeasureMaxLength = 0;
     820          246 :         Measure* m = toMeasure(mb);
     821              :         // if we are at the beginning of the line
     822              :         // we write the measure number
     823          246 :         if (currentLineLength == 0) {
     824           92 :             TextToUEBBraille textToBraille;
     825           92 :             QString measureNumber = textToBraille.braille(QString::number(m->measureNumber() + 1)).remove(0, 1) + " ";
     826           92 :             int measureNumberLen = measureNumber.size();
     827           92 :             line[0] += measureNumber;
     828           96 :             for (size_t i = 1; i < nrStaves; i++) {
     829            8 :                 line[i] += QString("").leftJustified(measureNumberLen);
     830              :             }
     831           92 :             currentLineLength += measureNumberLen;
     832           92 :         }
     833              : 
     834          246 :         if (m->hasMMRest() && m_score->style().styleB(Sid::createMultiMeasureRests)) {
     835            2 :             mb = m = m->mmRest();
     836              :         }
     837              : 
     838          500 :         for (size_t i = 0; i < nrStaves; ++i) {
     839              :             BRAILLE_TRACE() << "Measure " << m->measureNumber() + 1 << " Staff " << i;
     840              : 
     841          254 :             measureBraille[i] = brailleMeasure(m, static_cast<int>(i)).toUtf8();
     842              : 
     843          254 :             if (measureBraille[i].size() > currentMeasureMaxLength) {
     844          250 :                 currentMeasureMaxLength = measureBraille[i].size();
     845              :             }
     846              :         }
     847              : 
     848              :         BRAILLE_TRACE() << "Current measure max len: " << currentMeasureMaxLength;
     849              :         // TODO handle better the case when the size of the current measure
     850              :         // by itself is larger than the MAX_CHARS_PER_LINE. The measure will
     851              :         // have to be split on multiple lines based on specific rules
     852          246 :         if ((currentMeasureMaxLength + currentLineLength > MAX_CHARS_PER_LINE) && !measureAboveMax) {
     853           36 :             QTextStream out(&device);
     854           72 :             for (size_t i = 0; i < nrStaves; ++i) {
     855           36 :                 out << line[i].toUtf8() << Qt::endl;
     856           36 :                 line[i] = QString();
     857              :             }
     858           36 :             out.flush();
     859           36 :             currentLineLength = 0;
     860              :             // We need to re-render the current measure
     861              :             // as it will be on a new line.
     862           36 :             mb = mb->prev();
     863              :             // 3.2.1. Page 53. Music Braille Code 2015.
     864              :             // The octave is always marked for the first note of a braille line
     865           36 :             resetOctaves();
     866           36 :             if (currentMeasureMaxLength >= (MAX_CHARS_PER_LINE - 4)) {
     867            1 :                 measureAboveMax = true;
     868              :             }
     869           36 :             continue;
     870           36 :         }
     871              : 
     872          210 :         currentLineLength += currentMeasureMaxLength;
     873          428 :         for (size_t i = 0; i < nrStaves; ++i) {
     874          436 :             line[i] += measureBraille[i].leftJustified(currentMeasureMaxLength);
     875          218 :             measureBraille[i] = QString();
     876              :         }
     877              : 
     878          210 :         if (measureAboveMax || m->sectionBreak()) {
     879            2 :             QTextStream out(&device);
     880            4 :             for (size_t i = 0; i < nrStaves; ++i) {
     881            2 :                 out << line[i].toUtf8() << Qt::endl;
     882            2 :                 if (!lyrics[i].isEmpty()) {
     883            0 :                     out << lyrics[i].toUtf8() << Qt::endl;
     884              :                 }
     885            2 :                 line[i] = lyrics[i] = QString();
     886              :             }
     887            2 :             currentLineLength = 0;
     888              :             // 3.2.1. Page 53. Music Braille Code 2015.
     889              :             // The octave is always marked for the first note of a braille line
     890            2 :             resetOctaves();
     891            2 :             measureAboveMax = false;
     892            2 :             if (m->sectionBreak()) {
     893            1 :                 out << Qt::endl;
     894              :             }
     895            2 :             out.flush();
     896            2 :         }
     897              :     }
     898              : 
     899              :     // Write the last measures
     900           54 :     QTextStream out(&device);
     901          112 :     for (size_t i = 0; i < nrStaves; ++i) {
     902           58 :         out << line[i].toUtf8() << Qt::endl;
     903           58 :         line[i] = QString();
     904              :     }
     905           54 :     out.flush();
     906              : 
     907           54 :     return true;
     908           54 : }
     909              : 
     910            0 : bool Braille::convertMeasure(Measure* measure, BrailleEngravingItemList* beis)
     911              : {
     912            0 :     int nrStaves = static_cast<int>(m_score->staves().size());
     913              : 
     914            0 :     if (measure->hasMMRest() && m_score->style().styleB(Sid::createMultiMeasureRests)) {
     915            0 :         measure = measure->mmRest();
     916              :     }
     917              : 
     918            0 :     for (int i = 0; i < nrStaves; ++i) {
     919            0 :         BrailleEngravingItemList measureBraille;
     920            0 :         BrailleEngravingItemList measureLyrics;
     921              : 
     922            0 :         brailleMeasureItems(&measureBraille, measure, i);
     923              :         //measureBraille.log();
     924            0 :         beis->join(&measureBraille, true, false);
     925              : 
     926            0 :         brailleMeasureLyrics(&measureLyrics, measure, i);
     927            0 :         if (!measureLyrics.isEmpty()) {
     928            0 :             beis->join(&measureLyrics, true, false);
     929              :         }
     930            0 :     }
     931              : 
     932            0 :     return true;
     933              : }
     934              : 
     935            0 : bool Braille::convertItem(EngravingItem* el, BrailleEngravingItemList* beis)
     936              : {
     937            0 :     return brailleSingleItem(beis, el);
     938              : }
     939              : 
     940          361 : void Braille::resetOctave(size_t stave)
     941              : {
     942          361 :     m_context.previousNote[stave]  = nullptr;
     943          361 : }
     944              : 
     945           38 : void Braille::resetOctaves()
     946              : {
     947           76 :     for (size_t i = 0; i < m_score->staves().size(); ++i) {
     948           38 :         resetOctave(i);
     949              :     }
     950           38 : }
     951              : 
     952           54 : void Braille::credits(QIODevice& device)
     953              : {
     954           54 :     QTextStream out(&device);
     955              :     // find the vboxes in every page and write their elements as credit-words
     956          108 :     for (const auto page : m_score->pages()) {
     957          168 :         for (const auto system : page->systems()) {
     958          378 :             for (const auto mb : system->measures()) {
     959          264 :                 if (mb->isVBox()) {
     960          163 :                     for (const EngravingItem* element : mb->el()) {
     961          109 :                         if (element->isText()) {
     962          109 :                             const Text* text = toText(element);
     963          109 :                             out << TextToUEBBraille().braille(text->plainText()).toUtf8() << Qt::endl;
     964              :                         }
     965              :                     }
     966              :                 }
     967              :             }
     968              :         }
     969              :     }
     970              : 
     971           54 :     QStringList creators;
     972              :     // the creator types commonly found in MusicXML
     973           54 :     creators << "arranger" << "composer" << "lyricist" << "poet" << "translator";
     974          324 :     for (const QString& type : creators) {
     975          270 :         QString creator = m_score->metaTag(type);
     976          270 :         if (!creator.isEmpty()) {
     977          156 :             out << TextToUEBBraille().braille(QString("%1 %2").arg(type).arg(creator)).toUtf8() << Qt::endl;
     978              :         }
     979          270 :     }
     980           54 :     if (!m_score->metaTag(u"copyright").isEmpty()) {
     981            0 :         out << TextToUEBBraille().braille(QString("© %2").arg(m_score->metaTag(u"copyright"))).toUtf8() << Qt::endl;
     982              :     }
     983           54 :     out << Qt::endl;
     984           54 :     out.flush();
     985           54 : }
     986              : 
     987           54 : void Braille::instruments(QIODevice& device)
     988              : {
     989              :     //Print staff number to instrument mapping.
     990           54 :     QTextStream out(&device);
     991          112 :     for (size_t i = 0; i < m_score->staves().size(); ++i) {
     992          174 :         out << TextToUEBBraille().braille(QString("%1 %2").arg(i + 1).arg(m_score->staves()[i]->part()->instrumentName())) << Qt::endl;
     993              :     }
     994           54 :     out << Qt::endl;
     995           54 :     out.flush();
     996           54 : }
     997              : 
     998         1247 : int Braille::computeInterval(Note* note1, Note* note2, bool ignoreOctave)
     999              : {
    1000              :     // TODO is it possible to not have pitch?
    1001              :     // if yes, then this algorithm will fail in that case
    1002              : 
    1003         1247 :     QList<QString> initNotes;
    1004         1247 :     if (note1->epitch() < note2->epitch()) {
    1005          584 :         initNotes << "A" << "B" << "C" << "D" << "E" << "F" << "G";
    1006              :     } else {
    1007          663 :         initNotes << "G" << "F" << "E" << "D" << "C" << "B" << "A";
    1008              :     }
    1009              : 
    1010         1247 :     String note1PitchName;
    1011         1247 :     String note2PitchName;
    1012         1247 :     String accidental; //We don't need this, but tpc2name requires it
    1013         1247 :     tpc2name(note1->tpc(), NoteSpellingType::STANDARD, NoteCaseType::UPPER, note1PitchName, accidental);
    1014         1247 :     tpc2name(note2->tpc(), NoteSpellingType::STANDARD, NoteCaseType::UPPER, note2PitchName, accidental);
    1015              : 
    1016         1247 :     QList<QString> notes;
    1017         1247 :     int rootNodeIdx = initNotes.indexOf(note1PitchName);
    1018         6080 :     for (int i = rootNodeIdx; i < initNotes.size(); i++) {
    1019         4833 :         notes << initNotes.at(i);
    1020              :     }
    1021         5143 :     for (int i = 0; i < rootNodeIdx; i++) {
    1022         3896 :         notes << initNotes.at(i);
    1023              :     }
    1024              : 
    1025         1247 :     int interval = notes.indexOf(note2PitchName) + 1;
    1026         1247 :     if (!ignoreOctave && std::abs(note1->epitch() - note2->epitch()) >= 12) {
    1027           33 :         interval += (std::abs(note1->epitch() - note2->epitch()) / 12) * 8 - 1;
    1028              :     }
    1029              : 
    1030         1247 :     return interval;
    1031         1247 : }
    1032              : 
    1033         1173 : std::vector<Slur*> Braille::slurs(ChordRest* chordRest)
    1034              : {
    1035         1173 :     std::vector<Slur*> result;
    1036         1173 :     SpannerMap& smap = m_score->spannerMap();
    1037         1173 :     auto spanners = smap.findOverlapping(chordRest->tick().ticks(), chordRest->tick().ticks());
    1038         1525 :     for (auto interval : spanners) {
    1039          352 :         Spanner* spanner = interval.value;
    1040          352 :         if (spanner && spanner->isSlur()
    1041          299 :             && spanner->track() == chordRest->track()
    1042          704 :             && spanner->effectiveTrack2() == chordRest->track()) {
    1043          299 :             result.push_back(toSlur(spanner));
    1044              :         }
    1045              :     }
    1046              : 
    1047         1173 :     return result;
    1048         1173 : }
    1049              : 
    1050         1111 : std::vector<Hairpin*> Braille::hairpins(ChordRest* chordRest)
    1051              : {
    1052         1111 :     std::vector<Hairpin*> result;
    1053         1111 :     SpannerMap& smap = m_score->spannerMap();
    1054         1111 :     auto spanners = smap.findOverlapping(chordRest->tick().ticks(), chordRest->tick().ticks());
    1055         1382 :     for (auto interval : spanners) {
    1056          271 :         Spanner* spanner = interval.value;
    1057          271 :         if (spanner && spanner->isHairpin()
    1058           26 :             && spanner->track() == chordRest->track()
    1059          542 :             && spanner->effectiveTrack2() == chordRest->track()) {
    1060           26 :             result.push_back(toHairpin(spanner));
    1061              :         }
    1062              :     }
    1063              : 
    1064         1111 :     return result;
    1065         1111 : }
    1066              : 
    1067          868 : int Braille::notesInSlur(Slur* slur)
    1068              : {
    1069          868 :     int result = 0;
    1070         5409 :     for (Segment* segment = slur->startSegment(); segment; segment = segment->next1()) {
    1071         5409 :         if (!segment->isChordRestType()) {
    1072          439 :             continue;
    1073              :         }
    1074              : 
    1075         4970 :         ChordRest* cr = toChordRest(segment->element(slur->track()));
    1076         4970 :         if (!cr) {
    1077            0 :             continue;
    1078              :         }
    1079              : 
    1080              :         // Notes in tie do not count in slur.
    1081              :         // See Bar 5, Example 13.5.1.b, page 98. Music Braille Code 2015
    1082         4970 :         if (cr->isChord() && cr != slur->endCR() && segment->next1()) {
    1083         3973 :             Chord* chord = toChord(cr);
    1084         3973 :             bool skip = false;
    1085         7892 :             for (Note* note : chord->notes()) {
    1086         4051 :                 if (note->tieFor() && note->tieFor()->endNote()->chord() == segment->next1()->nextChordRest(chord->track())) {
    1087          132 :                     skip = true;
    1088          132 :                     break;
    1089              :                 }
    1090              :             }
    1091         3973 :             if (skip) {
    1092          132 :                 continue;
    1093              :             }
    1094              :         }
    1095              : 
    1096         4838 :         result++;
    1097         4838 :         if (segment == slur->endSegment()) {
    1098          868 :             break;
    1099              :         }
    1100              :     }
    1101          868 :     return result;
    1102              : }
    1103              : 
    1104          868 : bool Braille::isShortSlur(Slur* slur)
    1105              : {
    1106          868 :     int notesNr = notesInSlur(slur);
    1107              : 
    1108              :     //13.2. Page 94. Braille Music Code 2015.
    1109          868 :     if (notesNr <= 4) {
    1110          403 :         return true;
    1111              :     }
    1112          465 :     return false;
    1113              : }
    1114              : 
    1115          610 : bool Braille::isLongSlur(Slur* slur)
    1116              : {
    1117              :     //13.3. Page 94. Braille Music Code 2015.
    1118          610 :     return !isShortSlur(slur);
    1119              : }
    1120              : 
    1121           62 : bool Braille::isShortShortSlurConvergence(const std::vector<Slur*>& slurs)
    1122              : {
    1123          131 :     for (Slur* slur1 : slurs) {
    1124          164 :         for (Slur* slur2 : slurs) {
    1125           95 :             if (slur1 != slur2
    1126           23 :                 && isShortSlur(slur1)
    1127           13 :                 && isShortSlur(slur2)
    1128          118 :                 && (slur1->startCR() == slur2->endCR() || slur2->startCR() == slur1->endCR())) {
    1129            3 :                 return true;
    1130              :             }
    1131              :         }
    1132              :     }
    1133           59 :     return false;
    1134              : }
    1135              : 
    1136          409 : bool Braille::isLongLongSlurConvergence(const std::vector<Slur*>& slurs)
    1137              : {
    1138          869 :     for (Slur* slur1 : slurs) {
    1139         1030 :         for (Slur* slur2 : slurs) {
    1140          570 :             if (slur1 != slur2
    1141          108 :                 && isLongSlur(slur1)
    1142           58 :                 && isLongSlur(slur2)
    1143          678 :                 && (slur1->startCR() == slur2->endCR() || slur2->startCR() == slur1->endCR())) {
    1144            2 :                 return true;
    1145              :             }
    1146              :         }
    1147              :     }
    1148          407 :     return false;
    1149              : }
    1150              : 
    1151           65 : bool Braille::hasTies(ChordRest* chordRest)
    1152              : {
    1153           65 :     if (chordRest->isRest()) {
    1154            1 :         return false;
    1155              :     }
    1156              : 
    1157           64 :     Chord* chord = toChord(chordRest);
    1158          134 :     for (Note* note : chord->notes()) {
    1159           73 :         if (note->tieFor()) {
    1160            3 :             return true;
    1161              :         }
    1162              :     }
    1163              : 
    1164           61 :     return false;
    1165              : }
    1166              : 
    1167         1057 : bool Braille::ascendingChords(ClefType clefType)
    1168              : {
    1169              :     // 9.2. Direction of Intervals (in Chords). Page 75. Music Braille Code 2015
    1170              :     // In Treble, Soprano, Alto clefs: Write the highest note, then give remaining notes as intervals downward.
    1171              :     // In Tenor, Baritone, Bass clefs: Write the lowest note, then give remaining notes as intervals upward.
    1172              :     // All intervals are relative to the original (highest or lowest) note.
    1173         1057 :     switch (clefType) {
    1174          674 :     case ClefType::G:              //Treble clef
    1175              :     case ClefType::G15_MB:         //Treble clef 15ma bassa
    1176              :     case ClefType::G8_VB:          //Treble clef 8va bassa
    1177              :     case ClefType::G8_VA:          //Treble clef 8va alta
    1178              :     case ClefType::G15_MA:         //Treble clef 15ma alta
    1179              :     case ClefType::G8_VB_O:        //Double treble clef 8va bassa on 2nd line
    1180              :     case ClefType::G8_VB_P:        //Treble clef optional 8va bassa
    1181              :     case ClefType::G_1:            //French violin clef
    1182              :     case ClefType::C1:             //Soprano clef
    1183              :     case ClefType::C1_F18C:        //Soprano clef (French, 18th century)
    1184              :     case ClefType::C1_F20C:        //Soprano clef (French, 20th century)
    1185              :     case ClefType::C2:             //Mezzo-soprano clef
    1186              :     case ClefType::C3:             //Alto clef
    1187              :     case ClefType::C3_F18C:        //Alto clef (French, 18th century)
    1188              :     case ClefType::C3_F20C:        //Alto clef (French, 20th century)
    1189              :     case ClefType::C_19C:          //C clef, H shape (19th century)
    1190              :     case ClefType::TAB:            //TAB
    1191              :     case ClefType::TAB4:           //TAB
    1192              :     case ClefType::TAB_SERIF:      //TAB
    1193              :     case ClefType::TAB4_SERIF:     //TAB
    1194          674 :         return false;
    1195          383 :     case ClefType::C4:             //Tenor clef
    1196              :     case ClefType::C4_8VB:         //Tenor clef ottava bassa
    1197              :     case ClefType::C4_F18C:        //Tenor clef (French, 18th century)
    1198              :     case ClefType::C4_F20C:        //Tenor clef (French, 20th century)
    1199              :     case ClefType::C5:             //Baritone clef (C clef)
    1200              :     case ClefType::F:              //Bass clef
    1201              :     case ClefType::F_F18C:         //F clef (French, 18th century)
    1202              :     case ClefType::F_19C:          //F clef (19th century)
    1203              :     case ClefType::F15_MB:         //Bass clef 15ma bassa
    1204              :     case ClefType::F8_VB:          //Bass clef 8va bassa
    1205              :     case ClefType::F_8VA:          //Bass clef 8va alta
    1206              :     case ClefType::F_15MA:         //Bass clef 15ma alta
    1207              :     case ClefType::F_B:            //Baritone clef (F clef)
    1208              :     case ClefType::F_C:            //Subbass clef
    1209          383 :         return true;
    1210            0 :     case ClefType::PERC:           //Percussion
    1211              :     case ClefType::PERC2:          //Percussion
    1212            0 :         return false;
    1213            0 :     default:
    1214            0 :         break;
    1215              :     }
    1216            0 :     return false;
    1217              : }
    1218              : 
    1219            3 : BarLine* Braille::firstBarline(Measure* measure, track_idx_t track)
    1220              : {
    1221            3 :     for (Segment* seg = measure->first(); seg; seg = seg->next()) {
    1222            3 :         EngravingItem* el = seg->element(track);
    1223            3 :         if (el && el->isChordRest()) {
    1224            2 :             return nullptr;
    1225              :         }
    1226            1 :         if (el && el->isBarLine()) {
    1227            1 :             return toBarLine(el);
    1228              :         }
    1229              :     }
    1230            0 :     return nullptr;
    1231              : }
    1232              : 
    1233          529 : BarLine* Braille::lastBarline(Measure* measure, track_idx_t track)
    1234              : {
    1235          547 :     for (Segment* seg = measure->last(); seg; seg = seg->prev()) {
    1236          547 :         EngravingItem* el = seg->element(track);
    1237          547 :         if (el && el->isBarLine()) {
    1238          529 :             return toBarLine(el);
    1239              :         }
    1240              :     }
    1241            0 :     return nullptr;
    1242              : }
    1243              : 
    1244            0 : bool Braille::brailleSingleItem(BrailleEngravingItemList* beiz, EngravingItem* el)
    1245              : {
    1246            0 :     resetOctaves();
    1247              : 
    1248            0 :     if (el->isMarker()) {
    1249            0 :         beiz->addEngravingItem(el, brailleMarker(toMarker(el)));
    1250            0 :         return true;
    1251            0 :     } else if (el->isJump()) {
    1252            0 :         beiz->addEngravingItem(el, brailleJump(toJump(el)));
    1253            0 :         return true;
    1254            0 :     } else if (el->isDynamic()) {
    1255            0 :         beiz->addEngravingItem(el, brailleDynamic(toDynamic(el)));
    1256            0 :         return true;
    1257            0 :     } else if (el->isClef()) {
    1258            0 :         beiz->addEngravingItem(el, brailleClef(toClef(el)));
    1259            0 :         return true;
    1260            0 :     } else if (el->isKeySig()) {
    1261            0 :         beiz->addEngravingItem(el, brailleKeySig(toKeySig(el)));
    1262            0 :         return true;
    1263            0 :     } else if (el->isTimeSig()) {
    1264            0 :         beiz->addEngravingItem(el, brailleTimeSig(toTimeSig(el)));
    1265            0 :         return true;
    1266            0 :     } else if (el->isMMRest()) {
    1267            0 :         beiz->addEngravingItem(el, brailleMMRest(toMMRest(el)));
    1268            0 :         return true;
    1269            0 :     } else if (el->isRest()) {
    1270            0 :         beiz->addEngravingItem(el, brailleRest(toRest(el)));
    1271            0 :         return true;
    1272            0 :     } else if (el->isChord()) {
    1273            0 :         beiz->addEngravingItem(el, brailleChord(toChord(el)));
    1274            0 :         return true;
    1275            0 :     } else if (el->isBreath()) {
    1276            0 :         beiz->addEngravingItem(el, brailleBreath(toBreath(el)));
    1277            0 :         return true;
    1278            0 :     } else if (el->isBarLine()) {
    1279            0 :         beiz->addEngravingItem(el, brailleBarline(toBarLine(el)));
    1280            0 :         return true;
    1281            0 :     } else if (el->isMeasureRepeat()) {
    1282            0 :         beiz->addEngravingItem(el, brailleMeasureRepeat(toMeasureRepeat(el)));
    1283            0 :         return true;
    1284            0 :     } else if (el->isBreath()) {
    1285            0 :         beiz->addEngravingItem(el, brailleBreath(toBreath(el)));
    1286            0 :         return true;
    1287            0 :     } else if (el->isLyrics()) {
    1288            0 :         beiz->addEngravingItem(el, brailleLyrics(toLyrics(el)));
    1289            0 :         return true;
    1290            0 :     } else if (el->isNote()) {
    1291            0 :         Note* note = toNote(el);
    1292            0 :         beiz->addEngravingItem(el, brailleChordRootNote(note->chord(), note));
    1293            0 :         return true;
    1294              :     }
    1295            0 :     return false;
    1296              : }
    1297              : 
    1298            0 : void Braille::brailleMeasureItems(BrailleEngravingItemList* beiz, Measure* measure, int staffCount)
    1299              : {
    1300              :     //QTextStream out(&rez);
    1301              :     //LOGD("Braille::brailleMeasure %d", staffCount);
    1302              :     //Render all repeats and jumps that are on the left
    1303            0 :     for (EngravingItem* el : measure->el()) {
    1304            0 :         if (el->isMarker()) {
    1305            0 :             Marker* marker = toMarker(el);
    1306            0 :             if (marker->textStyleType() == TextStyleType::REPEAT_LEFT) {
    1307            0 :                 beiz->addEngravingItem(el, brailleMarker(toMarker(el)));
    1308              :             }
    1309              :         }
    1310            0 :         if (el->isJump()) {
    1311            0 :             Jump* jump = toJump(el);
    1312            0 :             if (jump->textStyleType() == TextStyleType::REPEAT_LEFT) {
    1313            0 :                 beiz->addEngravingItem(el, brailleJump(toJump(el)));
    1314              :             }
    1315              :         }
    1316              :     }
    1317              : 
    1318            0 :     auto spanners = m_score->spannerMap().findOverlapping(measure->tick().ticks(), measure->endTick().ticks());
    1319            0 :     for (auto interval : spanners) {
    1320            0 :         Spanner* s = interval.value;
    1321            0 :         if (s && s->isVolta()) {
    1322            0 :             beiz->addEngravingItem(s, brailleVolta(measure, toVolta(s), staffCount));
    1323              :         }
    1324              :     }
    1325              : 
    1326              :     //Render everything that is in Voice 1
    1327            0 :     for (auto seg = measure->first(); seg; seg = seg->next()) {
    1328            0 :         for (EngravingItem* annotation : seg->annotations()) {
    1329            0 :             if (annotation->isTempoText()) {
    1330            0 :                 beiz->addEngravingItem(annotation, brailleTempoText(toTempoText(annotation), staffCount));
    1331              :             }
    1332            0 :             if (annotation->track() == staffCount * VOICES) {
    1333            0 :                 if (annotation->isDynamic()) {
    1334            0 :                     beiz->addEngravingItem(annotation, brailleDynamic(toDynamic(annotation)));
    1335              :                 }
    1336              :             }
    1337              :         }
    1338              : 
    1339            0 :         EngravingItem* el = seg->element(staffCount * VOICES);
    1340            0 :         if (!el) {
    1341            0 :             continue;
    1342              :         }
    1343              : 
    1344            0 :         if (el->isClef()) {
    1345            0 :             beiz->addEngravingItem(el, brailleClef(toClef(el)));
    1346            0 :         } else if (el->isKeySig()) {
    1347            0 :             beiz->addEngravingItem(el, brailleKeySig(toKeySig(el)));
    1348            0 :         } else if (el->isTimeSig()) {
    1349            0 :             beiz->addEngravingItem(el, brailleTimeSig(toTimeSig(el)));
    1350            0 :         } else if (el->isMMRest()) {
    1351            0 :             beiz->addEngravingItem(el, brailleMMRest(toMMRest(el)));
    1352            0 :         } else if (el->isRest()) {
    1353            0 :             beiz->addEngravingItem(el, brailleRest(toRest(el)));
    1354            0 :         } else if (el->isChord()) {
    1355            0 :             beiz->addEngravingItem(el, brailleChord(toChord(el)));
    1356            0 :         } else if (el->isBreath()) {
    1357            0 :             beiz->addEngravingItem(el, brailleBreath(toBreath(el)));
    1358            0 :         } else if (el->isBarLine() && toBarLine(el) != lastBarline(measure, el->track())) {
    1359            0 :             beiz->addEngravingItem(el, brailleBarline(toBarLine(el)));
    1360            0 :         } else if (el->isMeasureRepeat()) {
    1361            0 :             beiz->addEngravingItem(el, brailleMeasureRepeat(toMeasureRepeat(el)));
    1362              :         }
    1363              :     }
    1364              : 
    1365              :     // Render the rest of the voices
    1366            0 :     for (size_t i = 1; i < VOICES; ++i) {
    1367            0 :         if (measure->hasVoice(staffCount * VOICES + i)) {
    1368              :             // 11.1.1. Page 87. Music Braille Code 2015.
    1369              :             // All voices must be complete when writing the other voices in Braille.
    1370              :             // We exchange the voices to voice 0 and back for MuseScore to add the missing beats as rests
    1371              :             // Then we undo the change, so we don't have an altered score.
    1372              :             // TODO: Braille dot 5 should be put before the rests that appear in Braille, but are not originally in the score
    1373              :             /*
    1374              :             m_score->deselectAll();
    1375              :             m_score->select(measure, SelectType::RANGE, staffCount);
    1376              :             m_score->update();
    1377              :             m_score->startCmd();
    1378              :             ExchangeVoices::exchangeVoicesInSelection(m_score, 0, static_cast<int>(i));
    1379              :             m_score->endCmd();
    1380              :             m_score->startCmd();
    1381              :             ExchangeVoices::exchangeVoicesInSelection(m_score, 0, static_cast<int>(i));
    1382              :             m_score->endCmd();
    1383              : */
    1384            0 :             resetOctave(staffCount);
    1385              : 
    1386            0 :             QString in_accord = QString::fromStdString(translate2Braille(Braille_FullMeasureAccord.code));
    1387            0 :             BrailleEngravingItem bei = BrailleEngravingItem(BEIType::VoiceInAccord, NULL, in_accord);
    1388            0 :             beiz->insert(MAX_LIVE_BRAILLE_LENGTH, bei);
    1389              : 
    1390            0 :             for (auto seg = measure->first(); seg; seg = seg->next()) {
    1391            0 :                 EngravingItem* el = seg->element(staffCount * VOICES + i);
    1392            0 :                 if (!el) {
    1393            0 :                     continue;
    1394              :                 }
    1395              : 
    1396            0 :                 if (el->isRest()) {
    1397            0 :                     beiz->addEngravingItem(el, brailleRest(toRest(el)));
    1398              :                 }
    1399            0 :                 if (el->isChord()) {
    1400            0 :                     beiz->addEngravingItem(el, brailleChord(toChord(el)));
    1401              :                 }
    1402            0 :                 if (el->isBreath()) {
    1403            0 :                     beiz->addEngravingItem(el, brailleBreath(toBreath(el)));
    1404              :                 }
    1405              :             }
    1406            0 :             resetOctave(staffCount);
    1407              : 
    1408              :             // Undo filling the missing beats with rests, so we don't have an altered score.
    1409              :             //            m_score->undoRedo(true, nullptr);
    1410              :             //            m_score->undoRedo(true, nullptr);
    1411              :             //            m_score->deselectAll();
    1412            0 :         }
    1413              :     }
    1414              : 
    1415              :     //Render the barline
    1416            0 :     BarLine* bl = lastBarline(measure, staffCount * VOICES);
    1417            0 :     if (bl) {
    1418            0 :         beiz->addEngravingItem(bl, brailleBarline(bl));
    1419              :     }
    1420              : 
    1421              :     //Render repeats and jumps that are on the right
    1422            0 :     for (EngravingItem* el : measure->el()) {
    1423            0 :         if (el->isMarker()) {
    1424            0 :             Marker* marker = toMarker(el);
    1425            0 :             if (marker->textStyleType() == TextStyleType::REPEAT_RIGHT) {
    1426            0 :                 beiz->addEngravingItem(el, brailleMarker(toMarker(el)));
    1427              :             }
    1428              :         }
    1429            0 :         if (el->isJump()) {
    1430            0 :             Jump* jump = toJump(el);
    1431            0 :             if (jump->textStyleType() == TextStyleType::REPEAT_RIGHT) {
    1432            0 :                 beiz->addEngravingItem(el, brailleJump(toJump(el)));
    1433              :             }
    1434              :         }
    1435              :     }
    1436            0 : }
    1437              : 
    1438            0 : void Braille::brailleMeasureLyrics(BrailleEngravingItemList* beiz, Measure* measure, int staffCount)
    1439              : {
    1440            0 :     BrailleEngravingItemList lyrics[MAX_LYRICS_NUM];
    1441              : 
    1442            0 :     for (auto seg = measure->first(); seg; seg = seg->next()) {
    1443            0 :         if (!seg->isChordRestType()) {
    1444            0 :             continue;
    1445              :         }
    1446            0 :         for (voice_idx_t voice = 0; voice < VOICES; ++voice) {
    1447            0 :             if (measure->hasVoice(staffCount * VOICES + voice)) {
    1448            0 :                 ChordRest* cr = seg->cr(staffCount * VOICES + voice);
    1449            0 :                 if (cr && !cr->lyrics().empty()) {
    1450            0 :                     for (Lyrics* l : cr->lyrics()) {
    1451            0 :                         int verse = l->verse();
    1452            0 :                         lyrics[verse].addLyricsItem(l);
    1453              :                     }
    1454              :                 }
    1455              :             }
    1456              :         }
    1457              :     }
    1458              : 
    1459            0 :     for (int i=0; i < MAX_LYRICS_NUM; i++) {
    1460            0 :         if (lyrics[i].isEmpty()) {
    1461            0 :             lyrics[i].clear();
    1462              :         } else {
    1463            0 :             QString braille = QString::fromStdString(translate2Braille(Braille_LyricLineIndicator.code));
    1464            0 :             BrailleEngravingItem bei = BrailleEngravingItem(BEIType::LineIndicator, NULL, braille);
    1465            0 :             lyrics[i].insert(0, bei);
    1466            0 :             beiz->join(&lyrics[i], true, false);
    1467            0 :         }
    1468              :     }
    1469            0 : }
    1470              : 
    1471           99 : QString Braille::brailleAccidentalType(AccidentalType accidental)
    1472              : {
    1473           99 :     switch (accidental) {
    1474            0 :     case AccidentalType::NONE:               return QString();
    1475           39 :     case AccidentalType::FLAT:               return BRAILLE_ACC_FLAT;
    1476           11 :     case AccidentalType::NATURAL:            return BRAILLE_ACC_NATURAL;
    1477           47 :     case AccidentalType::SHARP:              return BRAILLE_ACC_SHARP;
    1478            0 :     case AccidentalType::SHARP2:             return BRAILLE_ACC_SHARP + BRAILLE_ACC_SHARP;
    1479            0 :     case AccidentalType::FLAT2:              return BRAILLE_ACC_FLAT + BRAILLE_ACC_FLAT;
    1480            0 :     case AccidentalType::NATURAL_FLAT:       return BRAILLE_ACC_NATURAL + BRAILLE_ACC_FLAT;     //extrapolated
    1481            0 :     case AccidentalType::NATURAL_SHARP:      return BRAILLE_ACC_NATURAL + BRAILLE_ACC_SHARP;     //extrapolated
    1482            0 :     case AccidentalType::SHARP_SHARP:        return BRAILLE_ACC_SHARP + BRAILLE_ACC_SHARP;
    1483            0 :     case AccidentalType::FLAT_ARROW_UP:      return BRAILLE_ACC_QUARTER_STEP + BRAILLE_ACC_FLAT;
    1484            0 :     case AccidentalType::FLAT_ARROW_DOWN:    return BRAILLE_ACC_3QUARTER_STEP + BRAILLE_ACC_FLAT;
    1485            0 :     case AccidentalType::NATURAL_ARROW_UP:   return BRAILLE_ACC_QUARTER_STEP + BRAILLE_ACC_SHARP;
    1486            0 :     case AccidentalType::NATURAL_ARROW_DOWN: return BRAILLE_ACC_QUARTER_STEP + BRAILLE_ACC_FLAT;
    1487            0 :     case AccidentalType::SHARP_ARROW_UP:     return BRAILLE_ACC_3QUARTER_STEP + BRAILLE_ACC_SHARP;
    1488            0 :     case AccidentalType::SHARP_ARROW_DOWN:   return BRAILLE_ACC_QUARTER_STEP + BRAILLE_ACC_SHARP;
    1489            0 :     case AccidentalType::SHARP2_ARROW_UP:    return BRAILLE_ACC_5QUARTER_STEP + BRAILLE_ACC_SHARP;     //extrapolated. not sure
    1490            0 :     case AccidentalType::SHARP2_ARROW_DOWN:  return BRAILLE_ACC_3QUARTER_STEP + BRAILLE_ACC_SHARP;
    1491            0 :     case AccidentalType::FLAT2_ARROW_UP:     return BRAILLE_ACC_3QUARTER_STEP + BRAILLE_ACC_FLAT;
    1492            0 :     case AccidentalType::FLAT2_ARROW_DOWN:   return BRAILLE_ACC_5QUARTER_STEP + BRAILLE_ACC_FLAT;     //extrapolated. not sure
    1493            0 :     case AccidentalType::MIRRORED_FLAT:      return BRAILLE_ACC_QUARTER_STEP + BRAILLE_ACC_FLAT;
    1494            0 :     case AccidentalType::MIRRORED_FLAT2:     return BRAILLE_ACC_3QUARTER_STEP + BRAILLE_ACC_FLAT;
    1495            2 :     case AccidentalType::SHARP_SLASH:        return BRAILLE_ACC_QUARTER_STEP + BRAILLE_ACC_SHARP;
    1496            2 :     case AccidentalType::SHARP_SLASH4:       return BRAILLE_ACC_3QUARTER_STEP + BRAILLE_ACC_SHARP;
    1497            0 :     case AccidentalType::FLAT_SLASH2:        return BRAILLE_ACC_FLAT;
    1498            0 :     case AccidentalType::FLAT_SLASH:         return BRAILLE_ACC_FLAT;
    1499            0 :     case AccidentalType::SHARP_SLASH3:       return BRAILLE_ACC_SHARP;
    1500            0 :     case AccidentalType::SHARP_SLASH2:       return BRAILLE_ACC_SHARP;
    1501              :     //TODO the rest of the accidentals
    1502            0 :     default:
    1503            0 :         break;
    1504              :     }
    1505            0 :     return QString();
    1506              : }
    1507              : 
    1508         1057 : QString Braille::brailleArpeggio(Arpeggio* arpeggio)
    1509              : {
    1510         1057 :     if (!arpeggio) {
    1511         1055 :         return QString();
    1512              :     }
    1513              : 
    1514              :     // Table 22. Page 17. Music Braille Code 2015.
    1515            2 :     QString result = QString();
    1516              :     // fix me - this is a simple heuristic. can we do better?
    1517            2 :     if (arpeggio->ldata()->arpeggioHeight > 200) {
    1518            2 :         result += BRAILLE_ARPEGGIO_MULTISTAVES;
    1519              :     }
    1520              : 
    1521            2 :     if (arpeggio->arpeggioType() == ArpeggioType::NORMAL
    1522            0 :         || arpeggio->arpeggioType() == ArpeggioType::UP
    1523            0 :         || arpeggio->arpeggioType() == ArpeggioType::UP_STRAIGHT
    1524            2 :         || arpeggio->arpeggioType() == ArpeggioType::BRACKET) {
    1525            2 :         result += BRAILLE_ARPEGGIO_UPWARD;
    1526              :     }
    1527              : 
    1528            2 :     if (arpeggio->arpeggioType() == ArpeggioType::DOWN
    1529            2 :         || arpeggio->arpeggioType() == ArpeggioType::DOWN_STRAIGHT) {
    1530            0 :         result += BRAILLE_ARPEGGIO_DOWNWARD;
    1531              :     }
    1532              : 
    1533            2 :     return result;
    1534            2 : }
    1535              : 
    1536           22 : QString Braille::brailleArticulation(Articulation* artic)
    1537              : {
    1538           22 :     switch (artic->symId()) {
    1539            5 :     case SymId::articAccentAbove:
    1540              :     case SymId::articAccentBelow:
    1541            5 :         return BRAILLE_ARTIC_ACCENT;
    1542            1 :     case SymId::articStaccatoAbove:
    1543              :     case SymId::articStaccatoBelow:
    1544            1 :         return BRAILLE_ARTIC_STACCATO;
    1545            2 :     case SymId::articStaccatissimoAbove:
    1546              :     case SymId::articStaccatissimoBelow:
    1547              :     case SymId::articStaccatissimoStrokeAbove:     //extrapolated
    1548              :     case SymId::articStaccatissimoStrokeBelow:     //extrapolated
    1549              :     case SymId::articStaccatissimoWedgeAbove:      //extrapolated
    1550              :     case SymId::articStaccatissimoWedgeBelow:      //extrapolated
    1551            2 :         return BRAILLE_ARTIC_STACCATISSIMO;
    1552            1 :     case SymId::articTenutoAbove:
    1553              :     case SymId::articTenutoBelow:
    1554            1 :         return BRAILLE_ARTIC_TENUTO;
    1555            2 :     case SymId::articTenutoStaccatoAbove:
    1556              :     case SymId::articTenutoStaccatoBelow:
    1557            2 :         return BRAILLE_ARTIC_TENUTO_STACCATO;
    1558            1 :     case SymId::articMarcatoAbove:
    1559              :     case SymId::articMarcatoBelow:
    1560            1 :         return BRAILLE_ARTIC_MARCATO;
    1561            1 :     case SymId::articAccentStaccatoAbove:
    1562              :     case SymId::articAccentStaccatoBelow:
    1563            2 :         return BRAILLE_ARTIC_STACCATO + BRAILLE_ARTIC_ACCENT;     //extrapolated
    1564            0 :     case SymId::articMarcatoStaccatoAbove:
    1565              :     case SymId::articMarcatoStaccatoBelow:
    1566            0 :         return BRAILLE_ARTIC_STACCATO + BRAILLE_ARTIC_MARCATO;     //extrapolated
    1567            0 :     case SymId::articMarcatoTenutoAbove:
    1568              :     case SymId::articMarcatoTenutoBelow:
    1569            0 :         return BRAILLE_ARTIC_MARCATO + BRAILLE_ARTIC_TENUTO;       //extrapolated
    1570            0 :     case SymId::articStressAbove:
    1571              :     case SymId::articStressBelow:
    1572            0 :         return QString();     //TODO
    1573            0 :     case SymId::articTenutoAccentAbove:
    1574              :     case SymId::articTenutoAccentBelow:
    1575            0 :         return BRAILLE_ARTIC_TENUTO + BRAILLE_ARTIC_ACCENT;     //extrapolated
    1576            0 :     case SymId::articUnstressAbove:
    1577              :     case SymId::articUnstressBelow:
    1578            0 :         return QString();     //TODO
    1579            0 :     case SymId::articSoftAccentAbove:
    1580              :     case SymId::articSoftAccentBelow:
    1581            0 :         return QString();     //TODO
    1582            0 :     case SymId::articSoftAccentStaccatoAbove:
    1583              :     case SymId::articSoftAccentStaccatoBelow:
    1584            0 :         return QString();     //TODO
    1585            0 :     case SymId::articSoftAccentTenutoAbove:
    1586              :     case SymId::articSoftAccentTenutoBelow:
    1587            0 :         return QString();     //TODO
    1588            0 :     case SymId::articSoftAccentTenutoStaccatoAbove:
    1589              :     case SymId::articSoftAccentTenutoStaccatoBelow:
    1590            0 :         return QString();     //TODO
    1591            0 :     case SymId::guitarFadeIn:
    1592            0 :         return BRAILLE_ARTIC_REVERSED_ACCENT;     // not sure
    1593            0 :     case SymId::guitarFadeOut:
    1594            0 :         return BRAILLE_ARTIC_EXPRESSIVE_ACCENT;     //not sure
    1595            0 :     case SymId::guitarVolumeSwell:
    1596            0 :         return BRAILLE_ARTIC_SWELL;
    1597            0 :     case SymId::stringsDownBow:
    1598            0 :         return BRAILLE_DOWN_BOW;
    1599            0 :     case SymId::stringsUpBow:
    1600            0 :         return BRAILLE_UP_BOW;
    1601            0 :     case SymId::pluckedLeftHandPizzicato:
    1602              :     case SymId::pluckedBuzzPizzicato:     // extrapolated. not sure
    1603              :     case SymId::pluckedSnapPizzicatoAbove:     // extrapolated. not sure
    1604              :     case SymId::pluckedSnapPizzicatoBelow:     // extrapolated. not sure
    1605            0 :         return BRAILLE_LEFT_HAND_PIZZICATO;
    1606            0 :     case SymId::ornamentTurn:
    1607            0 :         return BRAILLE_TURN_NOTE;
    1608            0 :     case SymId::ornamentTurnInverted:
    1609            0 :         return BRAILLE_INVERTED_TURN_NOTE;
    1610            0 :     case SymId::ornamentTrill:
    1611            0 :         return BRAILLE_TRILL;
    1612            4 :     case SymId::ornamentMordent:
    1613            4 :         return BRAILLE_MORDENT;
    1614            3 :     case SymId::ornamentShortTrill:
    1615            3 :         return BRAILLE_SHORT_TRILL;
    1616            1 :     case SymId::ornamentTremblement:
    1617            1 :         return BRAILLE_TREBLEMENT;
    1618            1 :     case SymId::ornamentPrallMordent:
    1619            1 :         return BRAILLE_PRALL_MORDENT;
    1620            0 :     case SymId::ornamentUpPrall:
    1621            0 :         return BRAILLE_UP_PRALL;
    1622            0 :     case SymId::ornamentPrecompMordentUpperPrefix:
    1623            0 :         return BRAILLE_MORDENT_WITH_UPPER_FIX;
    1624            0 :     case SymId::ornamentUpMordent:
    1625            0 :         return BRAILLE_UP_MORDENT;
    1626            0 :     case SymId::ornamentDownMordent:
    1627            0 :         return BRAILLE_DOWN_MORDENT;
    1628            0 :     case SymId::ornamentPrallDown:
    1629            0 :         return BRAILLE_PRALL_DOWN;
    1630            0 :     case SymId::ornamentPrallUp:
    1631            0 :         return BRAILLE_PRALL_UP;
    1632            0 :     case SymId::ornamentLinePrall:
    1633            0 :         return BRAILLE_LINE_PRALL;
    1634              :     //TODO. there are still more articulations
    1635            0 :     default:
    1636            0 :         break;
    1637              :     }
    1638            0 :     return QString();
    1639              : }
    1640              : 
    1641          267 : QString Braille::brailleBarline(BarLine* barline)
    1642              : {
    1643          267 :     if (!barline) {
    1644            0 :         return QString();
    1645              :     }
    1646              : 
    1647          267 :     if (barline->measure()->system()
    1648          267 :         && barline->measure()->system()->firstMeasure()
    1649          267 :         && barline->measure()->system()->firstMeasure()->segments().first() == barline->segment()
    1650          534 :         && barline->barLineType() == BarLineType::NORMAL) {
    1651              :         // This is the barline at the beginning of the system
    1652              :         // We don't need to render it
    1653            8 :         return QString();
    1654              :     }
    1655              : 
    1656          259 :     bool spaceAfter = false;
    1657          259 :     bool spaceBefore = false;
    1658          259 :     QString barlineBraille = QString();
    1659              : 
    1660          259 :     switch (barline->barLineType()) {
    1661              :     // Table 1. Page 2.  Music Braille Code 2015
    1662          173 :     case BarLineType::NORMAL:
    1663          173 :         barlineBraille = BRAILLE_BARLINE;
    1664          173 :         break;
    1665            1 :     case BarLineType::BROKEN:
    1666            1 :         barlineBraille = BRAILLE_BARLINE_BROKEN;
    1667            1 :         spaceBefore = true;
    1668            1 :         spaceAfter = true;
    1669            1 :         break;
    1670            3 :     case BarLineType::DOUBLE:
    1671            3 :         barlineBraille = BRAILLE_BARLINE_DOUBLE;
    1672            3 :         resetOctave(barline->staffIdx());
    1673            3 :         spaceAfter = true;
    1674            3 :         break;
    1675           72 :     case BarLineType::END:
    1676           72 :         resetOctave(barline->staffIdx());
    1677           72 :         barlineBraille = BRAILLE_BARLINE_END;
    1678           72 :         spaceAfter = true;
    1679           72 :         break;
    1680            0 :     case BarLineType::DOTTED:
    1681            0 :         barlineBraille = BRAILLE_BARLINE_DOTTED;
    1682            0 :         spaceBefore = true;
    1683            0 :         spaceAfter = true;
    1684            0 :         break;
    1685              :     // Start/End Repeat Table 17. Page 15. Music Braille Code 2015
    1686            3 :     case BarLineType::START_REPEAT:
    1687            3 :         resetOctave(barline->staffIdx());
    1688            3 :         barlineBraille = BRAILLE_BARLINE_START_REPEAT;
    1689            3 :         break;
    1690            7 :     case BarLineType::END_REPEAT:
    1691            7 :         resetOctave(barline->staffIdx());
    1692            7 :         barlineBraille = BRAILLE_BARLINE_END_REPEAT;
    1693            7 :         spaceAfter = true;
    1694            7 :         break;
    1695              :     //This sign was not present in the book. Extrapolated from the above two signs
    1696            0 :     case BarLineType::END_START_REPEAT:
    1697            0 :         barlineBraille = BRAILLE_BARLINE_START_REPEAT + " " + BRAILLE_BARLINE_END_REPEAT;
    1698            0 :         break;
    1699            0 :     case BarLineType::REVERSE_END:
    1700              :     //case BarLineType::REVERSE_FINALE: // duplicate of the above, alternative name
    1701              :     case BarLineType::HEAVY:
    1702              :     case BarLineType::DOUBLE_HEAVY:
    1703            0 :         break; // ToDo ?!
    1704              :     }
    1705              : 
    1706          259 :     QString fermataBraille = QString();
    1707          259 :     for (EngravingItem* el : barline->segment()->annotations()) {
    1708            0 :         if (el->isFermata()) {
    1709            0 :             fermataBraille = brailleFermata(toFermata(el));
    1710              :         }
    1711              :     }
    1712              : 
    1713              :     //This is a special case
    1714          259 :     if (!fermataBraille.isEmpty() && barline->barLineType() == BarLineType::NORMAL) {
    1715            0 :         barlineBraille = BRAILLE_BARLINE_DOTTED;
    1716            0 :         spaceBefore = true;
    1717            0 :         spaceAfter = true;
    1718              :     }
    1719              : 
    1720          259 :     QString musicalHypenBrailleBefore = QString();
    1721            0 :     QString musicalHypenBrailleAfter = QString();
    1722              : 
    1723              :     // 1.10.1. Page 43. Music Braille Code 2015.
    1724          517 :     if ((barline->barLineType() == BarLineType::BROKEN || barline->barLineType() == BarLineType::DOTTED)
    1725          517 :         && barline != lastBarline(barline->measure(), barline->track())) {
    1726            1 :         musicalHypenBrailleBefore = BRAILLE_MUSICAL_HYPEN;
    1727              :     }
    1728              : 
    1729              :     // 17.1. Page 120. Music Braille Code 2015.
    1730          515 :     if ((barline->barLineType() == BarLineType::START_REPEAT || barline->barLineType() == BarLineType::END_START_REPEAT)
    1731          515 :         && barline != firstBarline(barline->measure(), barline->track())) {
    1732            2 :         spaceBefore = true;
    1733            2 :         musicalHypenBrailleBefore = BRAILLE_MUSICAL_HYPEN;
    1734              :     }
    1735              : 
    1736              :     // 17.1. Page 120. Music Braille Code 2015.
    1737          511 :     if ((barline->barLineType() == BarLineType::END_REPEAT || barline->barLineType() == BarLineType::END_START_REPEAT)
    1738          511 :         && barline != lastBarline(barline->measure(), barline->track())) {
    1739            1 :         musicalHypenBrailleAfter = BRAILLE_MUSICAL_HYPEN;
    1740              :     }
    1741              : 
    1742              :     return
    1743              :         musicalHypenBrailleBefore
    1744          518 :         + (spaceBefore ? " " : "")
    1745          518 :         + barlineBraille
    1746          518 :         + fermataBraille
    1747         1036 :         + (spaceAfter ? " " : "")
    1748          259 :         + musicalHypenBrailleAfter;
    1749          259 : }
    1750              : 
    1751            2 : QString Braille::brailleBreath(Breath* breath)
    1752              : {
    1753            2 :     if (!breath) {
    1754            0 :         return QString();
    1755              :     }
    1756              : 
    1757            2 :     if (breath->isCaesura()) {
    1758            1 :         return BRAILLE_CAESURA;
    1759              :     } else {
    1760            1 :         return BRAILLE_BREATH;
    1761              :     }
    1762              : }
    1763              : 
    1764         1057 : QString Braille::brailleChord(Chord* chord)
    1765              : {
    1766              :     // 9.3 Interval Doubling and 9.5 Moving notes methods are not implemented as they are optional methods
    1767              : 
    1768         1057 :     if (!chord || chord->notes().empty()) {
    1769            0 :         return QString();
    1770              :     }
    1771              : 
    1772         1057 :     QString graceNoteMarking = brailleGraceNoteMarking(chord);
    1773         1057 :     QString graceNotesBefore = QString();
    1774         1066 :     for (Chord* graceChord : chord->graceNotesBefore()) {
    1775            9 :         graceNotesBefore += brailleChord(graceChord);
    1776              :     }
    1777              : 
    1778         1057 :     QString tupletBraille = brailleTuplet(chord->tuplet(), chord);
    1779              : 
    1780         1057 :     std::vector<Hairpin*> chordHairpins = hairpins(chord);
    1781         1057 :     QString hairpinBrailleBefore = brailleHairpinBefore(chord, chordHairpins);
    1782              : 
    1783              :     // 9.2. Direction of Intervals (in Chords). Page 75. Music Braille Code 2015
    1784              :     // In Treble, Soprano, Alto clefs: Write the highest note, then give remaining notes as intervals downward.
    1785              :     // In Tenor, Baritone, Bass clefs: Write the lowest note, then give remaining notes as intervals upward.
    1786              :     // All intervals are relative to the original (highest or lowest) note.
    1787         1057 :     std::vector<Note*> notes;
    1788         1057 :     if (ascendingChords(m_context.currentClefType[chord->staffIdx()])) {
    1789          845 :         for (auto it = chord->notes().begin(); it != chord->notes().end(); ++it) {
    1790          462 :             notes.push_back(*it);
    1791              :         }
    1792              :     } else {
    1793         1441 :         for (auto it = chord->notes().rbegin(); it != chord->notes().rend(); ++it) {
    1794          767 :             notes.push_back(*it);
    1795              :         }
    1796              :     }
    1797              : 
    1798         1057 :     Note* rootNote = notes.front();
    1799         1057 :     QString rootNoteBraille = brailleChordRootNote(chord, rootNote);
    1800              : 
    1801         1057 :     QString intervals = QString();
    1802         1229 :     for (auto it = notes.begin() + 1; it != notes.end(); ++it) {
    1803          172 :         intervals += brailleChordInterval(rootNote, notes, *it);
    1804              :     }
    1805              : 
    1806         1057 :     QString graceNotesAfter = QString();
    1807         1057 :     for (Chord* graceChord : chord->graceNotesAfter()) {
    1808            0 :         graceNotesAfter  += brailleChord(graceChord);
    1809              :     }
    1810              : 
    1811         1057 :     QString chordTieBraille = brailleTie(chord);
    1812              : 
    1813         1057 :     QString fermata = QString();
    1814         1068 :     for (EngravingItem* el : chord->segment()->annotations()) {
    1815           11 :         if (el->isFermata()) {
    1816            4 :             fermata = brailleFermata(toFermata(el));
    1817              :         }
    1818              :     }
    1819              : 
    1820         1057 :     QString articulationsBraille = QString();
    1821         1079 :     for (Articulation* artic : chord->articulations()) {
    1822           22 :         articulationsBraille += brailleArticulation(artic);
    1823              :     }
    1824              : 
    1825         1057 :     std::vector<Slur*> chordSlurs = slurs(chord);
    1826         1057 :     QString slurBrailleBefore = brailleSlurBefore(chord, chordSlurs);
    1827         1057 :     QString slurBrailleAfter  = brailleSlurAfter(chord, chordSlurs);
    1828              : 
    1829         1057 :     QString hairpinBrailleAfter = brailleHairpinAfter(chord, chordHairpins);
    1830              : 
    1831         1057 :     QString arpeggio = brailleArpeggio(chord->arpeggio());
    1832         1057 :     QString tremoloBraille = brailleTremolo(chord);
    1833         1057 :     QString glissandoLastNoteBraille = brailleGlissando(notes.back());
    1834              : 
    1835              :     // In Braille the order of elements is clearly defined
    1836         1057 :     QString result = QString();
    1837         1057 :     result += hairpinBrailleBefore;
    1838         1057 :     result += graceNotesBefore;
    1839         1057 :     result += graceNoteMarking;
    1840         1057 :     result += arpeggio;
    1841         1057 :     result += articulationsBraille;
    1842         1057 :     result += slurBrailleBefore;
    1843         1057 :     result += tupletBraille;
    1844         1057 :     result += rootNoteBraille;
    1845         1057 :     result += intervals;
    1846         1057 :     result += tremoloBraille;
    1847         1057 :     result += chordTieBraille;
    1848         1057 :     result += slurBrailleAfter;
    1849         1057 :     result += glissandoLastNoteBraille;
    1850              :     /* not really sure where grace notes that follow the chord should be put
    1851              :      * MBC 2015, doesn't mention them, so tentatively putting them here. */
    1852         1057 :     result += graceNotesAfter;
    1853         1057 :     result += hairpinBrailleAfter;
    1854         1057 :     result += fermata;
    1855              : 
    1856         1057 :     return result;
    1857         1057 : }
    1858              : 
    1859              : //-----------------------------------------------------------------------------------
    1860              : //   brailleChordInterval
    1861              : //    rootNote: The root note of the chord.
    1862              : //    notes: The notes in the chord in the order that they are brailled
    1863              : //    note:  The note for which we are currently representing the braille interval
    1864              : //    return the braille interval representation in the chord
    1865              : //-----------------------------------------------------------------------------------
    1866          172 : QString Braille::brailleChordInterval(Note* rootNote, const std::vector<Note*>& notes, Note* note)
    1867              : {
    1868          172 :     if (!rootNote || !note || notes.size() < 2) {
    1869            0 :         return QString();
    1870              :     }
    1871              : 
    1872          172 :     int interval = computeInterval(rootNote, note, true);
    1873          172 :     QString intervalBraille;
    1874              :     //Table 9. Intervals. Page 7. Music Braille Code 2015
    1875          172 :     switch (interval) {
    1876           20 :     case 1: intervalBraille = BRAILLE_OCTAVE;
    1877           20 :         break;
    1878            1 :     case 2: intervalBraille = BRAILLE_SECOND;
    1879            1 :         break;
    1880           58 :     case 3: intervalBraille = BRAILLE_THIRD;
    1881           58 :         break;
    1882           13 :     case 4: intervalBraille = BRAILLE_FOURTH;
    1883           13 :         break;
    1884           35 :     case 5: intervalBraille = BRAILLE_FIFTH;
    1885           35 :         break;
    1886           36 :     case 6: intervalBraille = BRAILLE_SIXTH;
    1887           36 :         break;
    1888            9 :     case 7: intervalBraille = BRAILLE_SEVENTH;
    1889            9 :         break;
    1890              :     }
    1891          172 :     QString noteOctaveBraille = QString();
    1892          172 :     QString noteAccidentalBraille = QString();
    1893          172 :     if (note->accidental() != nullptr) {
    1894            7 :         noteAccidentalBraille = brailleAccidentalType(note->accidental()->accidentalType());
    1895              :     }
    1896              : 
    1897              :     // 9.1.1. Page 74. Music Braille Code 2015.
    1898              :     // A note represented by an interval sign must be preceded by the appropriate octave mark when:
    1899              :     // (a) it forms a unison with the written note (the octave-interval sign is used with the appropriate octave mark),
    1900          172 :     if (interval == 1 && rootNote->octave() == note->octave()) {
    1901            1 :         noteOctaveBraille = brailleOctave(note->octave());
    1902              :     }
    1903          172 :     size_t noteIdx = muse::indexOf(notes, note);
    1904          172 :     int intervalWithPreviousNoteInChord = computeInterval(notes.at(noteIdx - 1), note, false);
    1905              :     // (b) it is the first or only interval and is more than an octave from the written note,
    1906          172 :     if (noteIdx == 1 && intervalWithPreviousNoteInChord > 8) {
    1907            1 :         noteOctaveBraille = brailleOctave(note->octave());
    1908              :     }
    1909              :     // (c) it is the second of two adjacent intervals that are an octave or more apart, or
    1910          172 :     if (noteIdx != 1 && intervalWithPreviousNoteInChord >= 8) {
    1911            2 :         noteOctaveBraille = brailleOctave(note->octave());
    1912              :     }
    1913              :     // (d) it forms a unison with another interval that has been given previously in the chord.
    1914          172 :     if (noteIdx != 1 && intervalWithPreviousNoteInChord == 1) {
    1915            1 :         noteOctaveBraille = brailleOctave(note->octave());
    1916              :     }
    1917              : 
    1918          344 :     QString noteTieBraille = brailleTie(note);
    1919              : 
    1920            0 :     QString fingeringAfterBraille = QString();
    1921          172 :     for (EngravingItem* el : rootNote->el()) {
    1922            0 :         if (el->isFingering()) {
    1923            0 :             fingeringAfterBraille += brailleFingeringAfter(toFingering(el));
    1924              :         }
    1925              :     }
    1926              : 
    1927              :     return
    1928              :         noteAccidentalBraille
    1929          344 :         + noteOctaveBraille
    1930          344 :         + intervalBraille
    1931          516 :         + fingeringAfterBraille
    1932          172 :         + noteTieBraille;
    1933          172 : }
    1934              : 
    1935         1057 : QString Braille::brailleChordRootNote(Chord* chord, Note* rootNote)
    1936              : {
    1937         1057 :     String pitchName;
    1938         1057 :     String accidental; //TODO, do we need this for anything?
    1939         1057 :     String octaveBraille;
    1940         1057 :     tpc2name(rootNote->tpc(), NoteSpellingType::STANDARD, NoteCaseType::UPPER, pitchName, accidental);
    1941         1057 :     QString noteBraille = brailleNote(pitchName, chord->durationType().type(), chord->dots());
    1942              : 
    1943         1057 :     int octave = rootNote->octave();
    1944              :     // 3.2.1. Page 53. Music Braille Code 2015.
    1945              :     // Octave signs at the beginning of the line or when the melodic line is interrupted by specific elements
    1946         1057 :     if (!this->m_context.previousNote[chord->staffIdx()]) {
    1947          154 :         octaveBraille = brailleOctave(octave);
    1948              :     }
    1949              :     // 3.2.2. Octave signs in a melodic progression. Page 53. Music Braille Code 2015.
    1950              :     // a. the octave is not marked for the second of two consecutive notes if the interval is less than a fourth
    1951              :     // b. the octave is always marked in a skip greater than a fifth
    1952              :     // c. the octave is only marked in a skip of a fourth or fifth when the second note is in a different octave from the first.
    1953              :     else {
    1954          903 :         int interval = computeInterval(m_context.previousNote[chord->staffIdx()], rootNote, false);
    1955          903 :         if (interval > 5 || (interval > 3 && (m_context.previousNote[chord->staffIdx()]->octave() != rootNote->octave()))) {
    1956           65 :             octaveBraille = brailleOctave(octave);
    1957              :         }
    1958              :     }
    1959         1057 :     m_context.previousNote[chord->staffIdx()] = rootNote;
    1960              : 
    1961         1057 :     QString accidentalBraille = QString();
    1962         1057 :     if (rootNote->accidental()) {
    1963           33 :         accidentalBraille = brailleAccidentalType(rootNote->accidental()->accidentalType());
    1964              :     }
    1965              : 
    1966         1057 :     QString noteTieBraille = brailleTie(rootNote);
    1967              : 
    1968         1057 :     QString fingeringAfterBraille = QString();
    1969         1073 :     for (EngravingItem* el : rootNote->el()) {
    1970           16 :         if (el->isFingering()) {
    1971           16 :             fingeringAfterBraille += brailleFingeringAfter(toFingering(el));
    1972              :         }
    1973              :     }
    1974              : 
    1975              :     return
    1976              :         accidentalBraille
    1977         2114 :         + octaveBraille
    1978         2114 :         + noteBraille
    1979         2114 :         + fingeringAfterBraille
    1980         2114 :         + noteTieBraille;
    1981         1057 : }
    1982              : 
    1983           67 : QString Braille::brailleClef(Clef* clef)
    1984              : {
    1985              :     //In Braille, the clef is printed only at it's first appearance.
    1986           67 :     if (m_context.currentClefType[clef->staffIdx()] == clef->clefType()) {
    1987            7 :         return QString();
    1988              :     }
    1989              : 
    1990           60 :     m_context.currentClefType[clef->staffIdx()] = clef->clefType();
    1991           60 :     resetOctave(clef->staffIdx());
    1992              : 
    1993           60 :     switch (clef->clefType()) {
    1994           35 :     case ClefType::G:              //Treble clef
    1995           35 :         return BRAILLE_TREBLE_CLEF;
    1996            0 :     case ClefType::G15_MB:         //Treble clef 15ma bassa
    1997            0 :         return BRAILLE_TREBLE_CLEF_15MB;
    1998            0 :     case ClefType::G8_VB:          //Treble clef 8va bassa
    1999            0 :         return BRAILLE_TREBLE_CLEF_8VB;
    2000            0 :     case ClefType::G8_VA:          //Treble clef 8va alta
    2001            0 :         return BRAILLE_TREBLE_CLEF_8VA;
    2002            0 :     case ClefType::G15_MA:         //Treble clef 15ma alta
    2003            0 :         return BRAILLE_TREBLE_CLEF_15MA;
    2004            0 :     case ClefType::G8_VB_O:        //Double treble clef 8va bassa on 2nd line
    2005            0 :         return BRAILLE_D_TREBLE_CLEF_8VB_O;
    2006            0 :     case ClefType::G8_VB_P:        //Treble clef optional 8va bassa
    2007            0 :         return BRAILLE_TREBLE_CLEF_8VB_P;
    2008            0 :     case ClefType::G_1:            //French violin clef
    2009            0 :         return BRAILLE_FRENCH_VIOLINE_CLEF;
    2010            0 :     case ClefType::C1:             //Soprano clef
    2011              :     case ClefType::C1_F18C:        //Soprano clef (French, 18th century)
    2012              :     case ClefType::C1_F20C:        //Soprano clef (French, 20th century)
    2013            0 :         return BRAILLE_SOPRANO_CLEF;
    2014            0 :     case ClefType::C2:             //Mezzo-soprano clef
    2015            0 :         return BRAILLE_MEZZO_SOPRANO_CLEF;
    2016            0 :     case ClefType::C3:             //Alto clef
    2017              :     case ClefType::C3_F18C:        //Alto clef (French, 18th century)
    2018              :     case ClefType::C3_F20C:        //Alto clef (French, 20th century)
    2019              :     case ClefType::C_19C:          //C clef, H shape (19th century)
    2020            0 :         return BRAILLE_ALTO_CLEF;
    2021            1 :     case ClefType::C4:             //Tenor clef
    2022              :     case ClefType::C4_8VB:         //Tenor clef ottava bassa
    2023              :     case ClefType::C4_F18C:        //Tenor clef (French, 18th century)
    2024              :     case ClefType::C4_F20C:        //Tenor clef (French, 20th century)
    2025            1 :         return BRAILLE_TENOR_CLEF;
    2026            0 :     case ClefType::C5:             //Baritone clef (C clef)
    2027            0 :         return BRAILLE_BARITONE_C_CLEF;
    2028           24 :     case ClefType::F:              //Bass clef
    2029              :     case ClefType::F_F18C:         //F clef (French, 18th century)
    2030              :     case ClefType::F_19C:          //F clef (19th century)
    2031           24 :         return BRAILLE_BASS_CLEF;
    2032            0 :     case ClefType::F15_MB:         //Bass clef 15ma bassa
    2033            0 :         return BRAILLE_BASS_CLEF_15MB;
    2034            0 :     case ClefType::F8_VB:          //Bass clef 8va bassa
    2035            0 :         return BRAILLE_BASS_CLEF_8VB;
    2036            0 :     case ClefType::F_8VA:          //Bass clef 8va alta
    2037            0 :         return BRAILLE_BASS_CLEF_8VA;
    2038            0 :     case ClefType::F_15MA:         //Bass clef 15ma alta
    2039            0 :         return BRAILLE_BASS_CLEF_15MA;
    2040            0 :     case ClefType::F_B:            //Baritone clef (F clef)
    2041            0 :         return BRAILLE_BARITONE_F_CLEF;
    2042            0 :     case ClefType::F_C:            //Subbass clef
    2043            0 :         return BRAILLE_SUBBASS_CLEF;
    2044            0 :     case ClefType::PERC:           //Percussion
    2045              :     case ClefType::PERC2:          //Percussion
    2046              :     case ClefType::TAB:            //TAB
    2047              :     case ClefType::TAB4:           //TAB
    2048              :     case ClefType::TAB_SERIF:      //TAB
    2049              :     case ClefType::TAB4_SERIF:     //TAB
    2050            0 :         return QString();
    2051            0 :     default:
    2052            0 :         return QString();
    2053              :     }
    2054              : }
    2055              : 
    2056            3 : QString Braille::brailleDynamic(Dynamic* dynamic)
    2057              : {
    2058            3 :     if (!dynamic || dynamic->plainText().isEmpty()) {
    2059            0 :         return QString();
    2060              :     }
    2061              : 
    2062            3 :     resetOctave(dynamic->staffIdx());
    2063              :     // Table 22C. Page 19. Music Braille Code 2015
    2064            3 :     return ">" + TextToUEBBraille().braille(dynamic->plainText());
    2065              : }
    2066              : 
    2067            4 : QString Braille::brailleFermata(Fermata* fermata)
    2068              : {
    2069            4 :     if (!fermata) {
    2070            0 :         return QString();
    2071              :     }
    2072              : 
    2073              :     // Table 22B. Page 18. Music Braille Code 2015.
    2074              :     // TODO Could not find dedicated Braille symbols for Henze
    2075              :     // or very long variants, so regular ones were used. Are there dedicated symbols?
    2076            4 :     switch (fermata->symId()) {
    2077            4 :     case SymId::fermataAbove:
    2078              :     case SymId::fermataBelow:
    2079            4 :         return BRAILLE_FERMATA;
    2080            0 :     case SymId::fermataVeryShortAbove:
    2081              :     case SymId::fermataVeryShortBelow:
    2082              :     case SymId::fermataShortHenzeAbove:
    2083              :     case SymId::fermataShortHenzeBelow:
    2084              :     case SymId::fermataShortAbove:
    2085              :     case SymId::fermataShortBelow:
    2086            0 :         return BRAILLE_SHORT_FERMATA;
    2087            0 :     case SymId::fermataVeryLongAbove:
    2088              :     case SymId::fermataVeryLongBelow:
    2089              :     case SymId::fermataLongHenzeAbove:
    2090              :     case SymId::fermataLongHenzeBelow:
    2091              :     case SymId::fermataLongAbove:
    2092              :     case SymId::fermataLongBelow:
    2093            0 :         return BRAILLE_LONG_FERMATA;
    2094            0 :     default:
    2095            0 :         break;
    2096              :     }
    2097            0 :     return QString();
    2098              : }
    2099              : 
    2100           16 : QString Braille::brailleFingeringAfter(Fingering* fingering)
    2101              : {
    2102              :     // 15.1 - 15.2. Page 108. Music Braille Code 2015.
    2103              :     // TODO: 15.3 - 15.4. Page 108. Music Braille Code 2015.
    2104           16 :     QString result = QString();
    2105           16 :     if (fingering->textStyleType() == TextStyleType::FINGERING
    2106           16 :         || fingering->textStyleType() == TextStyleType::LH_GUITAR_FINGERING) {
    2107           16 :         QString plainText = fingering->plainText();
    2108           38 :         for (QChar c : plainText) {
    2109           22 :             if (c == QChar('0')) {
    2110            0 :                 result += BRAILLE_FINGERING_OPEN;
    2111              :             }
    2112           22 :             if (c == QChar('1')) {
    2113            6 :                 result += BRAILLE_FINGERING_1ST;
    2114              :             }
    2115           22 :             if (c == QChar('2')) {
    2116            4 :                 result += BRAILLE_FINGERING_2ND;
    2117              :             }
    2118           22 :             if (c == QChar('3')) {
    2119            1 :                 result += BRAILLE_FINGERING_3RD;
    2120              :             }
    2121           22 :             if (c == QChar('4')) {
    2122            3 :                 result += BRAILLE_FINGERING_4TH;
    2123              :             }
    2124           22 :             if (c == QChar('5')) {
    2125            5 :                 result += BRAILLE_FINGERING_5TH;
    2126              :             }
    2127           22 :             if (c == QChar('-')) {
    2128            3 :                 result += BRAILLE_FINGERING_CHANGE;
    2129              :             }
    2130              :         }
    2131           16 :     }
    2132              : 
    2133           16 :     return result;
    2134            0 : }
    2135              : 
    2136         1057 : QString Braille::brailleGlissando(Note* note)
    2137              : {
    2138         1057 :     if (!note) {
    2139            0 :         return QString();
    2140              :     }
    2141              : 
    2142         1057 :     for (Spanner* spanner : note->spannerFor()) {
    2143            2 :         if (spanner->isGlissando()) {
    2144            2 :             return BRAILLE_GLISSANDO;
    2145              :         }
    2146              :     }
    2147              : 
    2148         1055 :     return QString();
    2149              : }
    2150              : 
    2151         1057 : QString Braille::brailleGraceNoteMarking(Chord* chord)
    2152              : {
    2153              :     // 16.2.1 - 16.2.3. Page 111 - 112. Music Braille Code 2015.
    2154              :     // TODO: doubling the grace note sign where there are more than 4 grace notes.
    2155              :     //       the book is not very clear how this doubling is done and how the user
    2156              :     //       understands where do grace notes end.
    2157         1057 :     if (!chord->isGrace() || !chord->ownershipParent()->isChord()) {
    2158         1048 :         return QString();
    2159              :     }
    2160              : 
    2161            9 :     QString result = QString();
    2162            9 :     if (chord->stemSlash()) {
    2163            6 :         result = BRAILLE_GRACE_SHORT;
    2164              :     } else {
    2165            3 :         result = BRAILLE_GRACE_LONG;
    2166              :     }
    2167            9 :     return result;
    2168            9 : }
    2169              : 
    2170            1 : QString Braille::brailleJump(Jump* jump)
    2171              : {
    2172            1 :     switch (jump->jumpType()) {
    2173            1 :     case JumpType::DC:
    2174            1 :         return BRAILLE_DA_CAPO;
    2175            0 :     case JumpType::DC_AL_FINE:
    2176            0 :         return BRAILLE_DA_CAPO_AL_FINE;
    2177            0 :     case JumpType::DC_AL_CODA:
    2178            0 :         return BRAILLE_DA_CAPO_AL_CODA;
    2179            0 :     case JumpType::DS_AL_CODA:
    2180            0 :         return BRAILLE_DAL_SEGNO_AL_CODA;
    2181            0 :     case JumpType::DS_AL_FINE:
    2182            0 :         return BRAILLE_DAL_SEGNO_AL_FINE;
    2183            0 :     case JumpType::DS:
    2184            0 :         return BRAILLE_DAL_SEGNO;
    2185            0 :     case JumpType::USER:
    2186            0 :         return QString(">") + TextToUEBBraille().braille(jump->plainText().toQString().toLower()) + QString("> ");
    2187            0 :     case JumpType::DC_AL_DBLCODA:
    2188              :     case JumpType::DS_AL_DBLCODA:
    2189              :     case JumpType::DSS:
    2190              :     case JumpType::DSS_AL_CODA:
    2191              :     case JumpType::DSS_AL_DBLCODA:
    2192              :     case JumpType::DSS_AL_FINE:
    2193            0 :         break;
    2194              :     }
    2195            0 :     return QString();
    2196              : }
    2197              : 
    2198           69 : QString Braille::brailleKeySig(KeySig* keySig)
    2199              : {
    2200              :     //In Braille, the key signature is printed only at it's first appearance.
    2201              :     //Paragraf 6.5. Page 61. Music Braille Code 2015.
    2202           69 :     if (!keySig || keySig->segment()->isKeySigAnnounceType()
    2203          138 :         || (m_context.currentKey[keySig->staffIdx()] == keySig->key() && !keySig->isCustom())) {
    2204            9 :         return QString();
    2205              :     }
    2206              : 
    2207           60 :     m_context.currentKey[keySig->staffIdx()] = keySig->key();
    2208           60 :     resetOctave(keySig->staffIdx());
    2209              : 
    2210           60 :     QString brailleKeySig = QString();
    2211           60 :     if (keySig->isCustom()) {
    2212              :         //Section 6.5.1. Page 62. Music Braille Code 2015.
    2213              :         //TODO
    2214              :     } else {
    2215              :         //Section 6.5. Page 61. Music Braille Code 2015.
    2216              :         //Table 6. Page 5. Music Braille Code 2015.
    2217           60 :         switch (keySig->key()) {
    2218            0 :         case Key::C_B: brailleKeySig = QString(TextToUEBBraille().braille("7") + brailleAccidentalType(AccidentalType::FLAT));
    2219            0 :             break;
    2220            0 :         case Key::G_B: brailleKeySig = QString(TextToUEBBraille().braille("6") + brailleAccidentalType(AccidentalType::FLAT));
    2221            0 :             break;
    2222            0 :         case Key::D_B: brailleKeySig = QString(TextToUEBBraille().braille("5") + brailleAccidentalType(AccidentalType::FLAT));
    2223            0 :             break;
    2224            0 :         case Key::A_B: brailleKeySig = QString(TextToUEBBraille().braille("4") + brailleAccidentalType(AccidentalType::FLAT));
    2225            0 :             break;
    2226           16 :         case Key::E_B: brailleKeySig = QString(brailleAccidentalType(AccidentalType::FLAT) + brailleAccidentalType(
    2227           24 :                                                    AccidentalType::FLAT) + brailleAccidentalType(AccidentalType::FLAT));
    2228            8 :             break;
    2229            3 :         case Key::B_B: brailleKeySig = QString(brailleAccidentalType(AccidentalType::FLAT) + brailleAccidentalType(AccidentalType::FLAT));
    2230            3 :             break;
    2231            3 :         case Key::F:   brailleKeySig = QString(brailleAccidentalType(AccidentalType::FLAT));
    2232            3 :             break;
    2233           29 :         case Key::C:   return QString();
    2234            8 :         case Key::G:   brailleKeySig = QString(brailleAccidentalType(AccidentalType::SHARP));
    2235            8 :             break;
    2236            5 :         case Key::D:   brailleKeySig = QString(brailleAccidentalType(AccidentalType::SHARP) + brailleAccidentalType(AccidentalType::SHARP));
    2237            5 :             break;
    2238            4 :         case Key::A:   brailleKeySig = QString(brailleAccidentalType(AccidentalType::SHARP) + brailleAccidentalType(
    2239            6 :                                                    AccidentalType::SHARP) + brailleAccidentalType(AccidentalType::SHARP));
    2240            2 :             break;
    2241            1 :         case Key::E:   brailleKeySig = QString(TextToUEBBraille().braille("4") + brailleAccidentalType(AccidentalType::SHARP));
    2242            1 :             break;
    2243            1 :         case Key::B:   brailleKeySig = QString(TextToUEBBraille().braille("5") + brailleAccidentalType(AccidentalType::SHARP));
    2244            1 :             break;
    2245            0 :         case Key::F_S: brailleKeySig = QString(TextToUEBBraille().braille("6") + brailleAccidentalType(AccidentalType::SHARP));
    2246            0 :             break;
    2247            0 :         case Key::C_S: brailleKeySig = QString(TextToUEBBraille().braille("7") + brailleAccidentalType(AccidentalType::SHARP));
    2248            0 :             break;
    2249            0 :         case Key::INVALID: return QString();
    2250            0 :         case Key::NUM_OF:  return QString();     //TODO What is this?
    2251            0 :         case Key::DELTA_ENHARMONIC: return QString();     //TODO What is this?
    2252              :         }
    2253              :     }
    2254              : 
    2255           31 :     if (keySig->segment()->prev() && !keySig->prevSegmentElement()->isClef()) {
    2256            0 :         brailleKeySig = " " + brailleKeySig;
    2257              :     }
    2258              : 
    2259           31 :     if (!keySig->nextSegmentElement()->isTimeSig()) {
    2260            2 :         brailleKeySig += " ";
    2261              :     }
    2262              : 
    2263           31 :     return brailleKeySig;
    2264           60 : }
    2265              : 
    2266            0 : QString Braille::brailleLyrics(Lyrics* lyrics)
    2267              : {
    2268            0 :     std::string txt = lyrics->plainText().toStdString();
    2269            0 :     return QString::fromStdString(braille_long_translate(table_for_literature.c_str(), txt));
    2270            0 : }
    2271              : 
    2272            1 : QString Braille::brailleMarker(Marker* marker)
    2273              : {
    2274            1 :     switch (marker->markerType()) {
    2275            0 :     case MarkerType::SEGNO:
    2276              :     case MarkerType::VARSEGNO:
    2277            0 :         return BRAILLE_SEGNO;
    2278            0 :     case MarkerType::CODA:
    2279              :     case MarkerType::VARCODA:
    2280              :     case MarkerType::CODETTA:
    2281            0 :         return BRAILLE_CODA;
    2282            1 :     case MarkerType::FINE:
    2283            1 :         return BRAILLE_FINE;
    2284            0 :     case MarkerType::TOCODA:
    2285              :     case MarkerType::TOCODASYM:
    2286              :     case MarkerType::DA_CODA:
    2287              :     case MarkerType::DA_DBLCODA:
    2288            0 :         return BRAILLE_TOCODA;
    2289            0 :     case MarkerType::USER:
    2290            0 :         return QString(">") + TextToUEBBraille().braille(marker->plainText().toQString().toLower()) + QString("> ");
    2291              :     }
    2292            0 :     return QString();
    2293              : }
    2294              : 
    2295          254 : QString Braille::brailleMeasure(Measure* measure, int staffCount)
    2296              : {
    2297          254 :     QString rez;
    2298          254 :     QTextStream out(&rez);
    2299              : 
    2300              :     //LOGD("Braille::brailleMeasure %d", staffCount);
    2301              :     //Render all repeats and jumps that are on the left
    2302          269 :     for (EngravingItem* el : measure->el()) {
    2303           15 :         if (el->isMarker()) {
    2304            1 :             Marker* marker = toMarker(el);
    2305            1 :             if (marker->textStyleType() == TextStyleType::REPEAT_LEFT) {
    2306            0 :                 out << brailleMarker(toMarker(el));
    2307              :             }
    2308              :         }
    2309           15 :         if (el->isJump()) {
    2310            1 :             Jump* jump = toJump(el);
    2311            1 :             if (jump->textStyleType() == TextStyleType::REPEAT_LEFT) {
    2312            0 :                 out << brailleJump(toJump(el));
    2313              :             }
    2314              :         }
    2315              :     }
    2316              : 
    2317          254 :     auto spanners = m_score->spannerMap().findOverlapping(measure->tick().ticks(), measure->endTick().ticks());
    2318          375 :     for (auto interval : spanners) {
    2319          121 :         Spanner* s = interval.value;
    2320          121 :         if (s && s->isVolta()) {
    2321           17 :             out << brailleVolta(measure, toVolta(s), staffCount);
    2322              :         }
    2323              :     }
    2324              : 
    2325              :     //Render everything that is in Voice 1
    2326         1806 :     for (auto seg = measure->first(); seg; seg = seg->next()) {
    2327         1563 :         for (EngravingItem* annotation : seg->annotations()) {
    2328           11 :             if (annotation->isTempoText()) {
    2329            4 :                 out << brailleTempoText(toTempoText(annotation), staffCount);
    2330              :             }
    2331           11 :             if (annotation->track() == staffCount * VOICES) {
    2332           11 :                 if (annotation->isDynamic()) {
    2333            3 :                     out << brailleDynamic(toDynamic(annotation));
    2334              :                 }
    2335              :             }
    2336              :         }
    2337              : 
    2338         1552 :         EngravingItem* el = seg->element(staffCount * VOICES);
    2339         1552 :         if (!el) {
    2340           27 :             continue;
    2341              :         }
    2342              : 
    2343         1525 :         if (el->isClef()) {
    2344           67 :             out << brailleClef(toClef(el));
    2345         1458 :         } else if (el->isKeySig()) {
    2346           69 :             out << brailleKeySig(toKeySig(el));
    2347         1389 :         } else if (el->isTimeSig()) {
    2348           74 :             out << brailleTimeSig(toTimeSig(el));
    2349         1315 :         } else if (el->isMMRest()) {
    2350            2 :             out << brailleMMRest(toMMRest(el));
    2351         1313 :         } else if (el->isRest()) {
    2352           48 :             out << brailleRest(toRest(el));
    2353         1265 :         } else if (el->isChord()) {
    2354          993 :             out << brailleChord(toChord(el));
    2355          272 :         } else if (el->isBreath()) {
    2356            2 :             out << brailleBreath(toBreath(el));
    2357          270 :         } else if (el->isBarLine() && toBarLine(el) != lastBarline(measure, el->track())) {
    2358           13 :             out << brailleBarline(toBarLine(el));
    2359          257 :         } else if (el->isMeasureRepeat()) {
    2360            0 :             out << brailleMeasureRepeat(toMeasureRepeat(el));
    2361              :         }
    2362              :     }
    2363              : 
    2364              :     // Render the rest of the voices
    2365         1016 :     for (size_t i = 1; i < VOICES; ++i) {
    2366          762 :         if (measure->hasVoice(staffCount * VOICES + i)) {
    2367              :             // 11.1.1. Page 87. Music Braille Code 2015.
    2368              :             // All voices must be complete when writing the other voices in Braille.
    2369              :             // We exchange the voices to voice 0 and back for MuseScore to add the missing beats as rests
    2370              :             // Then we undo the change, so we don't have an altered score.
    2371              :             // TODO: Braille dot 5 should be put before the rests that appear in Braille, but are not originally in the score
    2372              : /* FIXME: may break live braille but be required for export
    2373              :             m_score->deselectAll();
    2374              :             m_score->select(measure, SelectType::RANGE, staffCount);
    2375              :             m_score->update();
    2376              :             m_score->startCmd();
    2377              :             ExchangeVoices::exchangeVoicesInSelection(m_score, 0, static_cast<int>(i));
    2378              :             m_score->endCmd();
    2379              :             m_score->startCmd();
    2380              :             ExchangeVoices::exchangeVoicesInSelection(m_score, 0, static_cast<int>(i));
    2381              :             m_score->endCmd();
    2382              : */
    2383              : 
    2384           12 :             resetOctave(staffCount);
    2385           12 :             out << BRAILLE_FULL_MEASURE_IN_ACORD;
    2386          129 :             for (auto seg = measure->first(); seg; seg = seg->next()) {
    2387          117 :                 EngravingItem* el = seg->element(staffCount * VOICES + i);
    2388          117 :                 if (!el) {
    2389           56 :                     continue;
    2390              :                 }
    2391              : 
    2392           61 :                 if (el->isRest()) {
    2393            6 :                     out << brailleRest(toRest(el));
    2394              :                 }
    2395           61 :                 if (el->isChord()) {
    2396           55 :                     out << brailleChord(toChord(el));
    2397              :                 }
    2398           61 :                 if (el->isBreath()) {
    2399            0 :                     out << brailleBreath(toBreath(el));
    2400              :                 }
    2401              :             }
    2402           12 :             resetOctave(staffCount);
    2403              : 
    2404              :             // Undo filling the missing beats with rests, so we don't have an altered score.
    2405              : /* see FIXME above
    2406              :             m_score->undoRedo(true, nullptr);
    2407              :             m_score->undoRedo(true, nullptr);
    2408              : */
    2409           12 :             m_score->deselectAll();
    2410              :         }
    2411              :     }
    2412              : 
    2413              :     //Render the barline
    2414          254 :     BarLine* bl = lastBarline(measure, staffCount * VOICES);
    2415          254 :     out << brailleBarline(bl);
    2416              : 
    2417              :     //Render repeats and jumps that are on the right
    2418          269 :     for (EngravingItem* el : measure->el()) {
    2419           15 :         if (el->isMarker()) {
    2420            1 :             Marker* marker = toMarker(el);
    2421            1 :             if (marker->textStyleType() == TextStyleType::REPEAT_RIGHT) {
    2422            1 :                 out << brailleMarker(toMarker(el));
    2423              :             }
    2424              :         }
    2425           15 :         if (el->isJump()) {
    2426            1 :             Jump* jump = toJump(el);
    2427            1 :             if (jump->textStyleType() == TextStyleType::REPEAT_RIGHT) {
    2428            1 :                 out << brailleJump(toJump(el));
    2429              :             }
    2430              :         }
    2431              :     }
    2432          254 :     out.flush();
    2433          254 :     return rez;
    2434          254 : }
    2435              : 
    2436            0 : QString Braille::brailleMeasureRepeat(MeasureRepeat* measureRepeat)
    2437              : {
    2438            0 :     if (!measureRepeat) {
    2439            0 :         return QString();
    2440              :     }
    2441              : 
    2442            0 :     return BRAILLE_MEASURE_REPEAT;
    2443              : }
    2444              : 
    2445            2 : QString Braille::brailleMMRest(MMRest* mmRest)
    2446              : {
    2447            2 :     if (!mmRest) {
    2448            0 :         return QString();
    2449              :     }
    2450              :     // 5.3 Multiple-Measure Rests. Page 58. MBC2015.
    2451              : 
    2452            2 :     if (mmRest->measure()->mmRestCount() <= 3) {
    2453            1 :         return BRAILLE_REST_MEASURE.repeated(mmRest->measure()->mmRestCount());
    2454              :     }
    2455              : 
    2456            1 :     resetOctave(mmRest->staffIdx());
    2457            2 :     return TextToUEBBraille().braille(QString::number(mmRest->measure()->mmRestCount())) + BRAILLE_REST_MEASURE;
    2458              : }
    2459              : 
    2460         1061 : QString Braille::brailleNote(const QString& pitchName, DurationType durationType, int dots)
    2461              : {
    2462         1061 :     QString noteBraille = QString();
    2463         1061 :     static QMap<DurationType, QMap<QString, QString> > noteToBraille;
    2464         1061 :     if (noteToBraille.isEmpty()) {
    2465              :         //8th and 128th notes have the same representation in Braille
    2466            1 :         noteToBraille[DurationType::V_128TH]["C"] = noteToBraille[DurationType::V_EIGHTH]["C"] = BRAILLE_C_8TH_128TH;
    2467            1 :         noteToBraille[DurationType::V_128TH]["D"] = noteToBraille[DurationType::V_EIGHTH]["D"] = BRAILLE_D_8TH_128TH;
    2468            1 :         noteToBraille[DurationType::V_128TH]["E"] = noteToBraille[DurationType::V_EIGHTH]["E"] = BRAILLE_E_8TH_128TH;
    2469            1 :         noteToBraille[DurationType::V_128TH]["F"] = noteToBraille[DurationType::V_EIGHTH]["F"] = BRAILLE_F_8TH_128TH;
    2470            1 :         noteToBraille[DurationType::V_128TH]["G"] = noteToBraille[DurationType::V_EIGHTH]["G"] = BRAILLE_G_8TH_128TH;
    2471            1 :         noteToBraille[DurationType::V_128TH]["A"] = noteToBraille[DurationType::V_EIGHTH]["A"] = BRAILLE_A_8TH_128TH;
    2472            1 :         noteToBraille[DurationType::V_128TH]["B"] = noteToBraille[DurationType::V_EIGHTH]["B"] = BRAILLE_B_8TH_128TH;
    2473              : 
    2474              :         //64th and quarter notes have the same representation in Braille
    2475            3 :         noteToBraille[DurationType::V_64TH]["C"] = noteToBraille[DurationType::V_QUARTER]["C"]
    2476            3 :                                                        = BRAILLE_C_64TH_QUARTER;
    2477            3 :         noteToBraille[DurationType::V_64TH]["D"] = noteToBraille[DurationType::V_QUARTER]["D"]
    2478            3 :                                                        = BRAILLE_D_64TH_QUARTER;
    2479            3 :         noteToBraille[DurationType::V_64TH]["E"] = noteToBraille[DurationType::V_QUARTER]["E"]
    2480            3 :                                                        = BRAILLE_E_64TH_QUARTER;
    2481            3 :         noteToBraille[DurationType::V_64TH]["F"] = noteToBraille[DurationType::V_QUARTER]["F"]
    2482            3 :                                                        = BRAILLE_F_64TH_QUARTER;
    2483            3 :         noteToBraille[DurationType::V_64TH]["G"] = noteToBraille[DurationType::V_QUARTER]["G"]
    2484            3 :                                                        = BRAILLE_G_64TH_QUARTER;
    2485            3 :         noteToBraille[DurationType::V_64TH]["A"] = noteToBraille[DurationType::V_QUARTER]["A"]
    2486            3 :                                                        = BRAILLE_A_64TH_QUARTER;
    2487            3 :         noteToBraille[DurationType::V_64TH]["B"] = noteToBraille[DurationType::V_QUARTER]["B"]
    2488            3 :                                                        = BRAILLE_B_64TH_QUARTER;
    2489              : 
    2490              :         //32nd and half notes have the same representation in Braille
    2491            1 :         noteToBraille[DurationType::V_32ND]["C"] = noteToBraille[DurationType::V_HALF]["C"] = BRAILLE_C_32ND_HALF;
    2492            1 :         noteToBraille[DurationType::V_32ND]["D"] = noteToBraille[DurationType::V_HALF]["D"] = BRAILLE_D_32ND_HALF;
    2493            1 :         noteToBraille[DurationType::V_32ND]["E"] = noteToBraille[DurationType::V_HALF]["E"] = BRAILLE_E_32ND_HALF;
    2494            1 :         noteToBraille[DurationType::V_32ND]["F"] = noteToBraille[DurationType::V_HALF]["F"] = BRAILLE_F_32ND_HALF;
    2495            1 :         noteToBraille[DurationType::V_32ND]["G"] = noteToBraille[DurationType::V_HALF]["G"] = BRAILLE_G_32ND_HALF;
    2496            1 :         noteToBraille[DurationType::V_32ND]["A"] = noteToBraille[DurationType::V_HALF]["A"] = BRAILLE_A_32ND_HALF;
    2497            1 :         noteToBraille[DurationType::V_32ND]["B"] = noteToBraille[DurationType::V_HALF]["B"] = BRAILLE_B_32ND_HALF;
    2498              : 
    2499              :         //16th and whole notes have the same representation in Braille.
    2500              :         // Breve has the same representation, but with an extra suffix;
    2501              :         // 256th has the same representation, but with an extra prefix;
    2502            3 :         noteToBraille[DurationType::V_256TH]["C"] = noteToBraille[DurationType::V_16TH]["C"]
    2503            2 :                                                         =noteToBraille[DurationType::V_WHOLE]["C"]
    2504            2 :                                                           = noteToBraille[DurationType::V_BREVE]["C"]
    2505            5 :                                                             = BRAILLE_C_16TH_WHOLE;
    2506              : 
    2507            3 :         noteToBraille[DurationType::V_256TH]["D"] = noteToBraille[DurationType::V_16TH]["D"]
    2508            2 :                                                         =noteToBraille[DurationType::V_WHOLE]["D"]
    2509            2 :                                                           = noteToBraille[DurationType::V_BREVE]["D"]
    2510            5 :                                                             = BRAILLE_D_16TH_WHOLE;
    2511              : 
    2512            3 :         noteToBraille[DurationType::V_256TH]["E"] = noteToBraille[DurationType::V_16TH]["E"]
    2513            2 :                                                         =noteToBraille[DurationType::V_WHOLE]["E"]
    2514            2 :                                                           = noteToBraille[DurationType::V_BREVE]["E"]
    2515            5 :                                                             = BRAILLE_E_16TH_WHOLE;
    2516              : 
    2517            3 :         noteToBraille[DurationType::V_256TH]["F"] = noteToBraille[DurationType::V_16TH]["F"]
    2518            2 :                                                         =noteToBraille[DurationType::V_WHOLE]["F"]
    2519            2 :                                                           = noteToBraille[DurationType::V_BREVE]["F"]
    2520            5 :                                                             = BRAILLE_F_16TH_WHOLE;
    2521              : 
    2522            3 :         noteToBraille[DurationType::V_256TH]["G"] = noteToBraille[DurationType::V_16TH]["G"]
    2523            2 :                                                         =noteToBraille[DurationType::V_WHOLE]["G"]
    2524            2 :                                                           = noteToBraille[DurationType::V_BREVE]["G"]
    2525            5 :                                                             = BRAILLE_G_16TH_WHOLE;
    2526              : 
    2527            3 :         noteToBraille[DurationType::V_256TH]["A"] = noteToBraille[DurationType::V_16TH]["A"]
    2528            2 :                                                         =noteToBraille[DurationType::V_WHOLE]["A"]
    2529            2 :                                                           = noteToBraille[DurationType::V_BREVE]["A"]
    2530            5 :                                                             = BRAILLE_A_16TH_WHOLE;
    2531              : 
    2532            3 :         noteToBraille[DurationType::V_256TH]["B"] = noteToBraille[DurationType::V_16TH]["B"]
    2533            2 :                                                         =noteToBraille[DurationType::V_WHOLE]["B"]
    2534            2 :                                                           = noteToBraille[DurationType::V_BREVE]["B"]
    2535            6 :                                                             = BRAILLE_B_16TH_WHOLE;
    2536              :     }
    2537              : 
    2538         1061 :     switch (durationType) {
    2539            0 :     case DurationType::V_LONG:      break;     //TODO
    2540            1 :     case DurationType::V_BREVE:
    2541            1 :         noteBraille = noteToBraille[DurationType::V_BREVE][pitchName] + BRAILLE_BREVE_SUFFIX;
    2542            1 :         break;
    2543         1060 :     case DurationType::V_WHOLE:
    2544              :     case DurationType::V_HALF:
    2545              :     case DurationType::V_QUARTER:
    2546              :     case DurationType::V_EIGHTH:
    2547              :     case DurationType::V_16TH:
    2548              :     case DurationType::V_32ND:
    2549              :     case DurationType::V_64TH:
    2550              :     case DurationType::V_128TH:
    2551         1060 :         noteBraille = QString(noteToBraille[durationType][pitchName]);
    2552         1060 :         break;
    2553            0 :     case DurationType::V_256TH:
    2554            0 :         noteBraille = BRAILLE_256TH_PREFIX + QString(noteToBraille[DurationType::V_256TH][pitchName]);
    2555            0 :         break;
    2556            0 :     case DurationType::V_512TH:     break;     //TODO not supported in braille?
    2557            0 :     case DurationType::V_1024TH:    break;     //TODO not supported in braille?
    2558            0 :     case DurationType::V_ZERO:      break;     //TODO
    2559            0 :     case DurationType::V_MEASURE:   break;     //TODO
    2560            0 :     case DurationType::V_INVALID:   break;
    2561              :     }
    2562              : 
    2563         1110 :     for (int i = 0; i < dots; ++i) {
    2564           49 :         noteBraille += BRAILLE_DURATION_DOT;
    2565              :     }
    2566              : 
    2567         1061 :     return noteBraille;
    2568            0 : }
    2569              : 
    2570          224 : QString Braille::brailleOctave(int octave)
    2571              : {
    2572              :     //Table 9. Page 7. Music Braille Code 2015.
    2573          224 :     if (octave < 1) {
    2574            2 :         return BRAILLE_BELOW_FIRST_OCTAVE;
    2575              :     }
    2576          222 :     if (octave == 1) {
    2577            1 :         return BRAILLE_1ST_OCTAVE;
    2578              :     }
    2579          221 :     if (octave == 2) {
    2580           47 :         return BRAILLE_2ND_OCTAVE;
    2581              :     }
    2582          174 :     if (octave == 3) {
    2583           44 :         return BRAILLE_3RD_OCTAVE;
    2584              :     }
    2585          130 :     if (octave == 4) {
    2586           78 :         return BRAILLE_4TH_OCTAVE;
    2587              :     }
    2588           52 :     if (octave == 5) {
    2589           48 :         return BRAILLE_5TH_OCTAVE;
    2590              :     }
    2591            4 :     if (octave == 6) {
    2592            1 :         return BRAILLE_6TH_OCTAVE;
    2593              :     }
    2594            3 :     if (octave == 7) {
    2595            1 :         return BRAILLE_7TH_OCTAVE;
    2596              :     }
    2597            2 :     if (octave > 7) {
    2598            2 :         return BRAILLE_ABOVE_7TH_OCTAVE;
    2599              :     }
    2600              : 
    2601            0 :     return QString();
    2602              : }
    2603              : 
    2604           54 : QString Braille::brailleRest(Rest* rest)
    2605              : {
    2606           54 :     QString restBraille;
    2607           54 :     switch (rest->durationType().type()) {
    2608            0 :     case DurationType::V_LONG:      restBraille = BRAILLE_REST_LONG;
    2609            0 :         break;
    2610            0 :     case DurationType::V_BREVE:     restBraille = BRAILLE_REST_BREVE;
    2611            0 :         break;
    2612            0 :     case DurationType::V_WHOLE:     restBraille = BRAILLE_REST_WHOLE;
    2613            0 :         break;
    2614            6 :     case DurationType::V_HALF:      restBraille = BRAILLE_REST_HALF;
    2615            6 :         break;
    2616           29 :     case DurationType::V_QUARTER:   restBraille = BRAILLE_REST_QUARTER;
    2617           29 :         break;
    2618           19 :     case DurationType::V_EIGHTH:    restBraille = BRAILLE_REST_EIGHTH;
    2619           19 :         break;
    2620            0 :     case DurationType::V_16TH:      restBraille = BRAILLE_REST_16TH;
    2621            0 :         break;
    2622            0 :     case DurationType::V_32ND:      restBraille = BRAILLE_REST_32ND;
    2623            0 :         break;
    2624            0 :     case DurationType::V_64TH:      restBraille = BRAILLE_REST_64TH;
    2625            0 :         break;
    2626            0 :     case DurationType::V_128TH:     restBraille = BRAILLE_REST_128TH;
    2627            0 :         break;
    2628            0 :     case DurationType::V_256TH:     restBraille = BRAILLE_REST_256TH;
    2629            0 :         break;
    2630            0 :     case DurationType::V_512TH:     restBraille = QString();
    2631            0 :         break;                                                                                //not supported in braille
    2632            0 :     case DurationType::V_1024TH:    restBraille = QString();
    2633            0 :         break;                                                                                //not supported in braille
    2634            0 :     case DurationType::V_ZERO:      restBraille = QString();
    2635            0 :         break;                                                                                //not sure what this means
    2636            0 :     case DurationType::V_MEASURE:   restBraille = BRAILLE_REST_MEASURE;
    2637            0 :         break;
    2638            0 :     case DurationType::V_INVALID:   restBraille = QString();
    2639            0 :         break;
    2640              :     }
    2641              : 
    2642           56 :     for (int i = 0; i < rest->dots(); ++i) {
    2643            2 :         restBraille += BRAILLE_DURATION_DOT;
    2644              :     }
    2645              : 
    2646           54 :     QString fermata = QString();
    2647           54 :     for (EngravingItem* el : rest->segment()->annotations()) {
    2648            0 :         if (el->isFermata()) {
    2649            0 :             fermata = brailleFermata(toFermata(el));
    2650              :         }
    2651              :     }
    2652          108 :     std::vector<Slur*> restSlurs = slurs(rest);
    2653          108 :     QString slurBrailleBefore = brailleSlurBefore(rest, restSlurs);
    2654          108 :     QString slurBrailleAfter  = brailleSlurAfter(rest, restSlurs);
    2655          108 :     std::vector<Hairpin*> restHairpins = hairpins(rest);
    2656          108 :     QString hairpinBrailleBefore = brailleHairpinBefore(rest, restHairpins);
    2657          108 :     QString hairpinBrailleAfter = brailleHairpinAfter(rest, restHairpins);
    2658              : 
    2659           54 :     QString tupletBraille = brailleTuplet(rest->tuplet(), rest);
    2660              : 
    2661           54 :     QString result = QString();
    2662           54 :     result += hairpinBrailleBefore;
    2663           54 :     result += slurBrailleBefore;
    2664           54 :     result += tupletBraille;
    2665           54 :     result += restBraille;
    2666           54 :     result += slurBrailleAfter;
    2667           54 :     result += hairpinBrailleAfter;
    2668           54 :     result += fermata;
    2669              : 
    2670          108 :     return result;
    2671           54 : }
    2672              : 
    2673            4 : QString Braille::brailleTempoText(TempoText* tempoText, int staffIdx)
    2674              : {
    2675            4 :     if (!tempoText) {
    2676            0 :         return QString();
    2677              :     }
    2678            4 :     resetOctave(staffIdx);
    2679              :     // Sections 1.8 and 1.8.1. Page 42. Music Braille Code 2015.
    2680            4 :     TDuration t1;
    2681            4 :     TDuration t2;
    2682              :     int len1;
    2683              :     int len2;
    2684            4 :     QString text = tempoText->plainText();
    2685            4 :     QString firstPart = text.split(" = ").first();
    2686            4 :     QString secondPart = text.split(" = ").back();
    2687            4 :     int x1 = TempoText::findTempoDuration(firstPart, len1, t1);
    2688            4 :     int x2 = TempoText::findTempoDuration(secondPart, len2, t2);
    2689              : 
    2690            4 :     if (x1 != -1) {
    2691            3 :         QString dots1;
    2692            3 :         QString dots2;
    2693            3 :         dots1 = brailleNote("C", t1.type(), t1.dots());
    2694            3 :         if (x2 != -1) {
    2695            1 :             dots2 = brailleNote("C", t2.type(), t2.dots());
    2696            1 :             QString result = BRAILLE_MUSIC_PARENTHESES + dots1 + BRAILLE_EQUALS_METRONOME + dots2 + BRAILLE_MUSIC_PARENTHESES;
    2697            1 :             result += " ";
    2698            1 :             return result;
    2699            1 :         } else {
    2700            4 :             QString result = BRAILLE_MUSIC_PARENTHESES + dots1 + BRAILLE_EQUALS_METRONOME + TextToUEBBraille().braille(secondPart)
    2701            6 :                              + BRAILLE_MUSIC_PARENTHESES;
    2702            2 :             result += " ";
    2703            2 :             return result;
    2704            2 :         }
    2705            3 :     } else {
    2706            1 :         return ">" + TextToUEBBraille().braille(text.toLower()) + "'";
    2707              :     }
    2708            4 : }
    2709              : 
    2710         1099 : QString Braille::brailleTie(Chord* chord)
    2711              : {
    2712              :     // This is not a chord
    2713         1099 :     if (!chord || chord->notes().size() < 2) {
    2714          974 :         return QString();
    2715              :     }
    2716              : 
    2717          125 :     int nrTies = 0;
    2718          125 :     Tie* firstTie = nullptr;
    2719          490 :     for (Note* note : chord->notes()) {
    2720          365 :         if (note->tieFor() != nullptr) {
    2721           94 :             if (firstTie == nullptr) {
    2722           39 :                 firstTie = note->tieFor();
    2723              :             }
    2724           94 :             nrTies++;
    2725              :         }
    2726              :     }
    2727              : 
    2728              :     // There are no notes in this chord with ties
    2729              :     // or there is just one note with tie
    2730          125 :     if (nrTies < 2) {
    2731           88 :         return QString();
    2732              :     }
    2733              : 
    2734              :     // There is at least one tie in the chord
    2735           37 :     Chord* nextChord = firstTie->endNote()->chord();
    2736          136 :     for (Note* chord1Note : chord->notes()) {
    2737          465 :         for (Note* chord2Note : nextChord->notes()) {
    2738          366 :             if (chord1Note->epitch() == chord2Note->epitch()
    2739          443 :                 && (!chord1Note->tieFor()
    2740           77 :                     || chord1Note->tieFor() != chord2Note->tieBack())) {
    2741              :                 // Not all notes with the same pitch are tied in the
    2742              :                 // two chords, so we cannot use the chord tie symbol;
    2743              :                 // Each note that is tied will receive individual note tie symbol.
    2744              :                 // 10.2-3. Page 83. Music Braille Code 2015.
    2745            9 :                 return QString();
    2746              :             }
    2747              :         }
    2748              :     }
    2749              : 
    2750           28 :     return BRAILLE_TIE_CHORD;
    2751              : }
    2752              : 
    2753         1229 : QString Braille::brailleTie(Note* note)
    2754              : {
    2755         1229 :     if (!note || !note->tieFor() || !brailleTie(note->chord()).isEmpty()) {
    2756         1207 :         return QString();
    2757              :     }
    2758              : 
    2759           22 :     return BRAILLE_TIE;
    2760              : }
    2761              : 
    2762           74 : QString Braille::brailleTimeSig(TimeSig* timeSig)
    2763              : {
    2764           74 :     if (!timeSig || timeSig->segment()->isTimeSigAnnounceType()) {
    2765            7 :         return QString();
    2766              :     }
    2767           67 :     resetOctave(timeSig->staffIdx());
    2768              : 
    2769           67 :     QString rez;
    2770           67 :     QTextStream rezult(&rez);
    2771           67 :     if (timeSig->timeSigType() == TimeSigType::FOUR_FOUR) {
    2772            3 :         return QString(".c");
    2773           64 :     } else if (timeSig->timeSigType() == TimeSigType::ALLA_BREVE) {
    2774            0 :         return QString("_c");
    2775              :     }
    2776           64 :     QMap<QString, QString> numeratorToBraille;
    2777           64 :     numeratorToBraille["1"] = 'a';
    2778           64 :     numeratorToBraille["2"] = 'b';
    2779           64 :     numeratorToBraille["3"] = 'c';
    2780           64 :     numeratorToBraille["4"] = 'd';
    2781           64 :     numeratorToBraille["5"] = 'e';
    2782           64 :     numeratorToBraille["6"] = 'f';
    2783           64 :     numeratorToBraille["7"] = 'g';
    2784           64 :     numeratorToBraille["8"] = 'h';
    2785           64 :     numeratorToBraille["9"] = 'i';
    2786           64 :     numeratorToBraille["0"] = 'j';
    2787              : 
    2788           64 :     QMap<QString, QString> denominatorToBraille;
    2789           64 :     denominatorToBraille["1"] = '1';
    2790           64 :     denominatorToBraille["2"] = '2';
    2791           64 :     denominatorToBraille["3"] = '3';
    2792           64 :     denominatorToBraille["4"] = '4';
    2793           64 :     denominatorToBraille["5"] = '5';
    2794           64 :     denominatorToBraille["6"] = '6';
    2795           64 :     denominatorToBraille["7"] = '7';
    2796           64 :     denominatorToBraille["8"] = '8';
    2797           64 :     denominatorToBraille["9"] = '9';
    2798           64 :     denominatorToBraille["0"] = '0';
    2799              : 
    2800           64 :     rezult << "#";
    2801              : 
    2802          130 :     for (QChar n : QString::number(timeSig->numerator())) {
    2803           66 :         rezult << numeratorToBraille[n];
    2804           64 :     }
    2805              : 
    2806          130 :     for (QChar d : QString::number(timeSig->denominator())) {
    2807           66 :         rezult << denominatorToBraille[d];
    2808           64 :     }
    2809              : 
    2810           64 :     rezult << " ";
    2811           64 :     rezult.flush();
    2812           64 :     return rez;
    2813           67 : }
    2814              : 
    2815         1057 : QString Braille::brailleTremolo(Chord* chord)
    2816              : {
    2817         1057 :     if (chord->tremoloChordType() == TremoloChordType::TremoloSecondChord) {
    2818            6 :         return QString();
    2819              :     }
    2820              : 
    2821         1051 :     switch (chord->tremoloType()) {
    2822           11 :     case TremoloType::R8:  return BRAILLE_TREMOLO_8THS;
    2823            6 :     case TremoloType::R16: return BRAILLE_TREMOLO_16THS;
    2824            1 :     case TremoloType::R32: return BRAILLE_TREMOLO_32NDS;
    2825            0 :     case TremoloType::R64: return BRAILLE_TREMOLO_64THS;
    2826            0 :     case TremoloType::R128: return BRAILLE_TREMOLO_128THS;
    2827            0 :     case TremoloType::R256: return QString(); // unsupported in braille
    2828            0 :     case TremoloType::C8:  return BRAILLE_TREMOLO_8THS_ALT;
    2829            2 :     case TremoloType::C16: return BRAILLE_TREMOLO_16THS_ALT;
    2830            4 :     case TremoloType::C32: return BRAILLE_TREMOLO_32NDS_ALT;
    2831            0 :     case TremoloType::C64: return BRAILLE_TREMOLO_64THS_ALT;
    2832            0 :     case TremoloType::C128: return BRAILLE_TREMOLO_128THS_ALT;
    2833            0 :     case TremoloType::C256: return QString(); // unsupported in braille
    2834            0 :     case TremoloType::BUZZ_ROLL: return QString();     //TODO
    2835         1027 :     case TremoloType::INVALID_TREMOLO: return QString();
    2836              :     }
    2837            0 :     return QString();
    2838              : }
    2839              : 
    2840         1111 : QString Braille::brailleTuplet(Tuplet* tuplet, DurationElement* el)
    2841              : {
    2842         1111 :     if (tuplet == nullptr || *tuplet->elements().begin() != el) {
    2843         1093 :         return QString();
    2844              :     }
    2845              : 
    2846           18 :     if (tuplet->ratio().numerator() == 3) {
    2847              :         // Special handling for triplets.
    2848           10 :         return QString("2"); // '⠆' (dots 2-3)
    2849              :     }
    2850              : 
    2851           16 :     return QString("_") + QString::number(tuplet->ratio().numerator()) + QString("'");
    2852              : }
    2853              : 
    2854           17 : QString Braille::brailleVolta(Measure* measure, Volta* volta, int staffCount)
    2855              : {
    2856           17 :     if (!volta || volta->startMeasure() != measure || volta->text().isEmpty()) {
    2857           10 :         return QString();
    2858              :     }
    2859              : 
    2860              :     // 17.1.1. Page 121. Music Braille Code 2015.
    2861            7 :     resetOctave(staffCount);
    2862            7 :     static const QRegularExpression regex("(,|\\.| )");
    2863           14 :     const QStringList voltaNumbers = volta->text().toQString().split(regex);
    2864            7 :     QString result = QString();
    2865           24 :     for (const QString& voltaNumber : voltaNumbers) {
    2866           17 :         if (voltaNumber.isEmpty()) {
    2867            8 :             continue;
    2868              :         }
    2869            9 :         result += QString("#") + voltaNumber;
    2870              :     }
    2871              : 
    2872              :     // Note: Normally the separator is only added in certain
    2873              :     // conditions, but for simplicity we add it everytime
    2874            7 :     result += "'";
    2875              : 
    2876            7 :     return result;
    2877            7 : }
    2878              : 
    2879         1111 : QString Braille::brailleHairpinBefore(ChordRest* chordRest, const std::vector<Hairpin*>& hairpins)
    2880              : {
    2881         1111 :     if (!chordRest) {
    2882            0 :         return QString();
    2883              :     }
    2884              :     //TODO we are supposed to use line continuation 1 and 2 if there are multiple lines overlapping
    2885         1111 :     QString result = QString();
    2886         1137 :     for (Hairpin* hairpin : hairpins) {
    2887           26 :         if (!hairpin || hairpin->startCR() != chordRest) {
    2888           20 :             continue;
    2889              :         }
    2890            6 :         QString beginTextBraille = QString();
    2891            6 :         if (!hairpin->beginText().isEmpty()) {
    2892              :             //TODO handle symbols
    2893            0 :             QString beginText = hairpin->beginText().toLower();
    2894            0 :             if (beginText.endsWith(".")) {
    2895            0 :                 beginText = beginText.left(beginText.lastIndexOf("."));
    2896              :             }
    2897            0 :             if (beginText.endsWith("'")) {
    2898            0 :                 beginText = beginText.left(beginText.lastIndexOf("'"));
    2899              :             }
    2900            0 :             beginTextBraille = QString(">") + TextToUEBBraille().braille(beginText);
    2901            0 :             resetOctave(hairpin->staffIdx());
    2902            0 :         }
    2903              : 
    2904            6 :         switch (hairpin->hairpinType()) {
    2905            2 :         case HairpinType::CRESC_HAIRPIN:
    2906            2 :             result += beginTextBraille + BRAILLE_HAIRPIN_DIV_START;
    2907            2 :             resetOctave(hairpin->staffIdx());
    2908            2 :             break;
    2909            4 :         case HairpinType::DIM_HAIRPIN:
    2910            4 :             result += beginTextBraille + BRAILLE_HAIRPIN_CONV_START;
    2911            4 :             resetOctave(hairpin->staffIdx());
    2912            4 :             break;
    2913            0 :         case HairpinType::CRESC_LINE:
    2914              :         case HairpinType::DIM_LINE:
    2915            0 :             result += beginTextBraille + BRAILLE_LINE_CONT_START_1;
    2916            0 :             resetOctave(hairpin->staffIdx());
    2917            0 :             break;
    2918            6 :         case HairpinType::INVALID:
    2919              :             ;
    2920              :         }
    2921            6 :     }
    2922              : 
    2923         1111 :     return result;
    2924         1111 : }
    2925              : 
    2926         1111 : QString Braille::brailleHairpinAfter(ChordRest* chordRest, const std::vector<Hairpin*>& hairpins)
    2927              : {
    2928         1111 :     if (!chordRest) {
    2929            0 :         return QString();
    2930              :     }
    2931              :     //TODO we are supposed to use line continuation 1 and 2 if there are multiple lines overlapping
    2932              : 
    2933              :     // 23.3.3.C says end of  *may* be omitted in some specific cases,
    2934              :     // but since it is not mandatory, we don't do it for simplicity.
    2935              :     // This needs to be accounted when using examples from MBC2015 for tests
    2936         1111 :     QString result = QString();
    2937         1137 :     for (Hairpin* hairpin : hairpins) {
    2938           26 :         if (!hairpin || hairpin->endCR() != chordRest) {
    2939           20 :             continue;
    2940              :         }
    2941            6 :         switch (hairpin->hairpinType()) {
    2942            2 :         case HairpinType::CRESC_HAIRPIN:
    2943            2 :             result += BRAILLE_HAIRPIN_DIV_END;
    2944            2 :             resetOctave(hairpin->staffIdx());
    2945            2 :             break;
    2946            4 :         case HairpinType::DIM_HAIRPIN:
    2947            4 :             result += BRAILLE_HAIRPIN_CONV_END;
    2948            4 :             resetOctave(hairpin->staffIdx());
    2949            4 :             break;
    2950            0 :         case HairpinType::CRESC_LINE:
    2951              :         case HairpinType::DIM_LINE:
    2952            0 :             result += BRAILLE_LINE_CONT_END_1;
    2953            0 :             resetOctave(hairpin->staffIdx());
    2954            0 :             break;
    2955           26 :         case HairpinType::INVALID:
    2956              :             ;
    2957              :         }
    2958              :     }
    2959         1111 :     return result;
    2960         1111 : }
    2961              : 
    2962         1111 : QString Braille::brailleSlurBefore(ChordRest* chordRest, const std::vector<Slur*>& slurs)
    2963              : {
    2964         1111 :     if (!chordRest || slurs.empty()) {
    2965          914 :         return QString();
    2966              :     }
    2967              : 
    2968              :     // 13.4 Page 98. Music Braille Code 2015.
    2969          197 :     if (isLongLongSlurConvergence(slurs)) {
    2970            2 :         return BRAILLE_SLUR_BRACKET_START + BRAILLE_SLUR_BRACKET_END;
    2971              :     }
    2972              : 
    2973          196 :     QString longSlur = QString();
    2974          418 :     for (Slur* slur : slurs) {
    2975              :         //13.3. Page 94. Braille Music Code 2015.
    2976          222 :         if (isLongSlur(slur) && chordRest->segment() == slur->startSegment()) {
    2977           17 :             longSlur += BRAILLE_SLUR_BRACKET_START;
    2978              :         }
    2979              :     }
    2980              : 
    2981              :     // TODO Implement 13.6 - 13.10.  Page 98. Music Braille Code 2015.
    2982              : 
    2983          196 :     return longSlur;
    2984          196 : }
    2985              : 
    2986         1111 : QString Braille::brailleSlurAfter(ChordRest* chordRest, const std::vector<Slur*>& crSlurs)
    2987              : {
    2988         1111 :     if (!chordRest || crSlurs.empty()) {
    2989          914 :         return QString();
    2990              :     }
    2991              : 
    2992              :     // 13.4 Page 98. Music Braille Code 2015.
    2993          197 :     if (isLongLongSlurConvergence(crSlurs)) {
    2994            1 :         return QString();
    2995              :     }
    2996              : 
    2997          196 :     bool hasShortSlurSymbol = false;
    2998          196 :     QString longSlurBraille = QString();
    2999          196 :     QString shortSlurBraille = QString();
    3000              : 
    3001          418 :     for (Slur* slur : crSlurs) {
    3002              :         // 13.2. Page 94. Braille Music Code 2015.
    3003              :         // 13.5. Page 98. Music Braille Code 2015. In Braille, slurs are redundant on notes with ties
    3004          222 :         if (isShortSlur(slur) && chordRest->segment() != slur->endSegment() && !hasTies(chordRest)) {
    3005           62 :             hasShortSlurSymbol = true;
    3006              :         }
    3007              : 
    3008              :         //13.3. Page 94. Braille Music Code 2015.
    3009          222 :         if (isLongSlur(slur) && chordRest->segment() == slur->endSegment() && !isLongLongSlurConvergence(crSlurs)) {
    3010           15 :             longSlurBraille += BRAILLE_SLUR_BRACKET_END;
    3011              :         }
    3012              :     }
    3013              : 
    3014          196 :     if (hasShortSlurSymbol) {
    3015           62 :         std::vector<Slur*> nextCRSlurs;
    3016           62 :         if (chordRest->segment()->next1()) {
    3017           62 :             ChordRest* nextCR = chordRest->segment()->next1()->nextChordRest(chordRest->track());
    3018           62 :             nextCRSlurs = slurs(nextCR);
    3019              :         }
    3020              : 
    3021              :         // 13.4 Page 98. Music Braille Code 2015.
    3022           62 :         if (isShortShortSlurConvergence(nextCRSlurs)) {
    3023            3 :             shortSlurBraille = BRAILLE_SLUR_SHORT_CONVERGENCE;
    3024              :         }
    3025              :         // 13.2. Page 94. Braille Music Code 2015.
    3026              :         else {
    3027           59 :             shortSlurBraille = BRAILLE_SLUR_SHORT;
    3028              :         }
    3029           62 :     }
    3030              :     // TODO Implement 13.6 - 13.10.  Page 98. Music Braille Code 2015.
    3031              : 
    3032          196 :     return shortSlurBraille + longSlurBraille;
    3033          196 : }
    3034              : }
        

Generated by: LCOV version 2.0-1