LCOV - code coverage report
Current view: top level - src/importexport/mei/internal - meiexporter.h Coverage Total Hit
Test: filtered_coverage.info Lines: 100.0 % 1 1
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              : #ifndef MU_IMPORTEXPORT_MEIEXPORTER_H
      24              : #define MU_IMPORTEXPORT_MEIEXPORTER_H
      25              : 
      26              : #include "engraving/types/types.h"
      27              : 
      28              : #include "modularity/ioc.h"
      29              : #include "imeiconfiguration.h"
      30              : 
      31              : #include "meiconverter.h"
      32              : 
      33              : #include "thirdparty/libmei/element.h"
      34              : #include "thirdparty/libmei/shared.h"
      35              : 
      36              : #include "pugixml.hpp"
      37              : 
      38              : namespace mu::engraving {
      39              : class Articulation;
      40              : class Beam;
      41              : class Chord;
      42              : class ChordLine;
      43              : class ChordRest;
      44              : class Clef;
      45              : class EngravingItem;
      46              : class Fingering;
      47              : class Lyrics;
      48              : class Measure;
      49              : class Note;
      50              : class Part;
      51              : class Rest;
      52              : class Score;
      53              : class Staff;
      54              : class TremoloSingleChord;
      55              : class TremoloTwoChord;
      56              : class Trill;
      57              : class Tuplet;
      58              : class VBox;
      59              : }
      60              : 
      61              : namespace mu::iex::mei {
      62              : class UIDRegister;
      63              : 
      64              : enum layerElementCounter {
      65              :     ACCID_L = 0,
      66              :     BEAM_L,
      67              :     HARM_L,
      68              :     GRACEGRP_L,
      69              :     SYL_L,
      70              :     VERSE_L,
      71              :     UNSPECIFIED_L,
      72              : };
      73              : 
      74              : /**
      75              :  * Class of exporting Music Encoding Initiative (MEI) files
      76              :  */
      77              : 
      78              : class MeiExporter
      79              : {
      80              : public:
      81              :     muse::GlobalInject<mu::iex::mei::IMeiConfiguration> configuration;
      82              : 
      83              : public:
      84           64 :     MeiExporter(engraving::Score* s) { m_score = s; }
      85              :     bool write(std::string& meiData);
      86              : 
      87              : private:
      88              :     bool writeHeader();
      89              :     bool writeScore();
      90              :     bool writeScoreDef();
      91              :     bool writePgHead(const engraving::VBox* vBox);
      92              :     bool writeLines(pugi::xml_node node, const muse::StringList& lines);
      93              :     bool writeLinesWithSMuFL(pugi::xml_node node, const muse::StringList& lines);
      94              :     bool writeScoreDefChange();
      95              :     bool writeStaffGrpStart(const engraving::Staff* staff, std::vector<int>& ends, const engraving::Part* part);
      96              :     bool writeStaffGrpEnd(const engraving::Staff* staff, std::vector<int>& ends);
      97              :     bool writeStaffDef(const engraving::Staff* staff, const engraving::Measure* measure, const engraving::Part* part, bool isPart);
      98              :     bool writeLabel(pugi::xml_node node, const engraving::Part* part);
      99              :     bool writeInstrDef(pugi::xml_node node, const engraving::Part* part);
     100              :     bool writeEnding(const engraving::Measure* measure);
     101              :     bool writeEndingEnd(const engraving::Measure* measure);
     102              :     bool writeMeasure(const engraving::Measure* measure, int& measureN, bool& isFirst, bool& wasLastIrregular);
     103              :     bool writeStaff(const engraving::Staff* staff, const engraving::Measure* measure);
     104              :     bool writeLayer(engraving::track_idx_t track, const engraving::Staff* staff, const engraving::Measure* measure);
     105              : 
     106              :     /**
     107              :      * Methods for writing MEI elements within a <layer>
     108              :      */
     109              :     bool writeArtics(const engraving::Chord* chord);
     110              :     bool writeArtic(const engraving::Articulation* articulation);
     111              :     bool writeArtic(const engraving::ChordLine* chordline);
     112              :     bool writeBeamAndTuplet(const engraving::ChordRest* chordRest, bool& closingBeam, bool& closingTuplet, bool& closingBeamInTuplet);
     113              :     bool writeBeamAndTupletEnd(bool closingBeam, bool closingTuplet, bool closingBeamInTuplet);
     114              :     bool writeBeam(const engraving::Beam* beam, const engraving::ChordRest* chordRest, bool& closing);
     115              :     bool writeBTrem(const engraving::TremoloSingleChord* tremolo);
     116              :     bool writeFTrem(const engraving::TremoloTwoChord* tremolo);
     117              :     bool writeClef(const engraving::Clef* clef);
     118              :     bool writeChord(const engraving::Chord* chord, const engraving::Staff* staff);
     119              :     bool writeGraceGrp(const engraving::Chord* chord, const engraving::Staff* staff, bool isAfter = false);
     120              :     bool writeNote(const engraving::Note* note, const engraving::Chord* chord, const engraving::Staff* staff, bool isChord);
     121              :     bool writeMRpt(const engraving::MeasureRepeat* measureRepeat);
     122              :     bool writeRest(const engraving::Rest* rest, const engraving::Staff* staff);
     123              :     bool writeSyl(const engraving::Lyrics* lyrics, const muse::String& text, ElisionType elision);
     124              :     bool writeTuplet(const engraving::Tuplet* tuplet, const engraving::EngravingItem* item, bool& closing);
     125              :     bool writeVerses(const engraving::ChordRest* chordRest);
     126              :     bool writeVerse(const engraving::Lyrics* lyrics);
     127              : 
     128              :     /**
     129              :      * Methods for writing MEI control events (within <measure>)
     130              :      */
     131              :     bool writeArpeg(const engraving::Arpeggio* arpeggio, const std::string& startid);
     132              :     bool writeBreath(const engraving::Breath* breath, const std::string& startid);
     133              :     bool writeDir(const engraving::TextBase* dir, const std::string& startid);
     134              :     bool writeDir(const engraving::TextLineBase* dir, const std::string& startid);
     135              :     bool writeDynam(const engraving::Dynamic* dynamic, const std::string& startid);
     136              :     bool writeF(const engraving::FiguredBassItem* figuredBassItem);
     137              :     bool writeFb(const engraving::FiguredBass* figuredBass, const std::string& startid);
     138              :     bool writeFermata(const engraving::Fermata* fermata, const std::string& startid);
     139              :     bool writeFermata(const engraving::Fermata* fermata, const libmei::xsdPositiveInteger_List& staffNs, double tstamp);
     140              :     bool writeFing(const engraving::Fingering* fing, const std::string& startid);
     141              :     bool writeGliss(const engraving::Glissando* gliss, const std::string& startid);
     142              :     bool writeHairpin(const engraving::Hairpin* hairpin, const std::string& startid);
     143              :     bool writeHarm(const engraving::Harmony* harmony, const std::string& startid);
     144              :     bool writeHarpPedal(const engraving::HarpPedalDiagram* harpPedalDiagram, const std::string& startid);
     145              :     bool writeOctave(const engraving::Ottava* ottava, const std::string& startid);
     146              :     bool writeOrnament(const engraving::Ornament* ornament, const std::string& startid);
     147              :     bool writePedal(const engraving::Pedal* pedal, const std::string& startid);
     148              :     bool writeRehearsalMark(const engraving::RehearsalMark* mark, const std::string& startid);
     149              :     bool writeRepeatMark(const engraving::Jump* jump, const engraving::Measure* measure);
     150              :     bool writeRepeatMark(const engraving::Marker* marker, const engraving::Measure* measure);
     151              :     bool writeSlur(const engraving::Slur* slur, const std::string& startid);
     152              :     bool writeTempo(const engraving::TempoText* tempoText, const std::string& startid);
     153              :     bool writeTie(const engraving::Tie* tie, const std::string& startid);
     154              :     bool writeTrill(const engraving::Trill* trill, const std::string& startid);
     155              : 
     156              :     /**
     157              :      * Methods for writing specific MEI attribute classes within elements
     158              :      */
     159              :     bool writeBeamTypeAtt(const engraving::ChordRest* chordRest, libmei::AttTyped& typeAtt);
     160              :     bool writeStaffIdentAtt(const engraving::ChordRest* chordRest, const engraving::Staff* staff, libmei::AttStaffIdent& staffIdentAtt);
     161              :     bool writeStemAtt(const engraving::Chord* chord, libmei::AttStems& stemsAtt);
     162              : 
     163              :     /**
     164              :      * Helper methods
     165              :      */
     166              :     bool isCurrentNode(const libmei::Element& element);
     167              :     std::vector<const engraving::Volta*> findVoltasInMeasure(const engraving::Measure* measure);
     168              :     void fillControlEventMap(const std::string& xmlId, const engraving::ChordRest* chordRest);
     169              :     std::string findStartIdFor(const engraving::EngravingItem* item);
     170              :     void addToRepeatMarkList(const engraving::EngravingItem* repeatMark, pugi::xml_node node, const std::string& xmlId);
     171              :     void addJumpToRepeatMarks();
     172              :     bool addFermataToMap(engraving::track_idx_t track, const engraving::Segment* segment, const engraving::Measure* measure);
     173              :     std::pair<libmei::xsdPositiveInteger_List, double> findTstampFor(const engraving::EngravingItem* item);
     174              :     bool isNode(pugi::xml_node node, const muse::String& name);
     175              :     pugi::xml_node getLastChordRest(pugi::xml_node node);
     176              :     void addNodeToOpenControlEvents(pugi::xml_node node, const engraving::Spanner* spanner, const std::string& startid);
     177              :     void addEndidToControlEvents();
     178              :     bool isLaissezVibrer(const engraving::SymId id);
     179              : 
     180              :     /**
     181              :      * Methods for generating @xml:ids
     182              :      */
     183              :     uint32_t hash(uint32_t number, bool reverse);
     184              :     std::string baseEncodeInt(uint32_t value, uint8_t base);
     185              :     std::string generateHashID();
     186              :     std::string getXmlIdFor(const engraving::EngravingItem* item, const char c);
     187              :     void resetLayerIDs();
     188              :     std::string getSectionXmlId();
     189              :     std::string getMeasureXmlId(const engraving::Measure* measure);
     190              :     std::string getStaffXmlId();
     191              :     std::string getLayerXmlId();
     192              :     std::string getLayerXmlIdFor(layerElementCounter elementType);
     193              : 
     194              :     /** A structure of holding a list of repeat marks to be post-process in addJumpToRepeatMarks (currently unused) */
     195              :     struct RepeatMark {
     196              :         const engraving::EngravingItem* m_repeatMark = nullptr;
     197              :         pugi::xml_node m_node;
     198              :         std::string m_xmlId;
     199              :         std::string m_jumptToLabel;
     200              :         std::string m_jumpToXmlId;
     201              :     };
     202              : 
     203              :     /** The Score pointer */
     204              :     engraving::Score* m_score = nullptr;
     205              : 
     206              :     /** The uid register */
     207              :     UIDRegister* m_uids;
     208              : 
     209              :     /** MEI xml element */
     210              :     pugi::xml_node m_mei;
     211              :     /** Current xml element */
     212              :     pugi::xml_node m_currentNode;
     213              : 
     214              :     /** When writing layers, keep a pointer to the keySig segment (if any) to prepend a scoreDef if necessary */
     215              :     const engraving::Segment* m_keySig;
     216              :     /** Same for the timeSig segment */
     217              :     const engraving::Segment* m_timeSig;
     218              :     /** A flag indicating that we have multiple sections in the file */
     219              :     bool m_hasSections;
     220              : 
     221              :     /** A list of items (first) for which we know the @startid (second)  */
     222              :     std::vector<std::pair<const engraving::EngravingItem*, std::string> > m_startingControlEventList;
     223              :     /** A map of items with the @endid they will need to have added */
     224              :     std::map<const engraving::EngravingItem*, std::string> m_endingControlEventMap;
     225              :     /** A map of items with the @plist value they will need to have added */
     226              :     std::map<const engraving::EngravingItem*, std::string> m_plistMap;
     227              :     /** A map of chord that are a plist of the arpeggio */
     228              :     std::map<const engraving::Chord*, const engraving::Arpeggio*> m_arpegPlistMap;
     229              :     /** A map of elements (e.g., Fermata) to which a tstamp will need to be added  */
     230              :     std::vector<std::pair<const engraving::EngravingItem*, std::pair<libmei::xsdPositiveInteger_List, double> > > m_tstampControlEventMap;
     231              :     /** A map of items with the corresponding node (to which the endid from m_endingControlEventMap or plist from m_plistMap will be added) */
     232              :     std::map<const engraving::EngravingItem*, pugi::xml_node> m_openControlEventMap;
     233              : 
     234              :     std::vector<MeiExporter::RepeatMark> m_repeatMarks;
     235              : 
     236              :     /** Counters for generating xml:ids */
     237              :     int m_xmlIDCounter;
     238              :     int m_sectionCounter;
     239              :     int m_measureCounter;
     240              :     int m_staffCounter;
     241              :     int m_layerCounter;
     242              :     /** Sub counters by elementType */
     243              :     std::vector<int> m_layerCounterFor;
     244              : 
     245              :     /** map of abbreviations for element within layers */
     246              :     inline static const std::map<layerElementCounter, muse::String> s_layerXmlIdMap = {
     247              :         { ACCID_L, u"a" },
     248              :         { BEAM_L, u"b" },
     249              :         { GRACEGRP_L, u"g" },
     250              :         { SYL_L, u"s" },
     251              :         { VERSE_L, u"v" },
     252              :         { UNSPECIFIED_L, u"x" }
     253              :     };
     254              : };
     255              : } // namespace
     256              : 
     257              : #endif // MU_IMPORTEXPORT_MEIEXPORTER_H
        

Generated by: LCOV version 2.0-1