LCOV - code coverage report
Current view: top level - src/importexport/mei/internal - meiimporter.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              : #pragma once
      24              : 
      25              : #include "engraving/types/types.h"
      26              : 
      27              : #include "modularity/ioc.h"
      28              : #include "imeiconfiguration.h"
      29              : #include "io/ifilesystem.h"
      30              : #include "io/path.h"
      31              : 
      32              : #include "meiconverter.h"
      33              : 
      34              : #include "thirdparty/libmei/cmn.h"
      35              : #include "thirdparty/libmei/element.h"
      36              : #include "thirdparty/libmei/shared.h"
      37              : 
      38              : #include "pugixml.hpp"
      39              : 
      40              : namespace mu::engraving {
      41              : class Chord;
      42              : class ChordRest;
      43              : class EngravingItem;
      44              : class Lyrics;
      45              : class Measure;
      46              : class Note;
      47              : class Part;
      48              : class Score;
      49              : class Spanner;
      50              : class Tuplet;
      51              : class VBox;
      52              : enum class NoteType : unsigned char;
      53              : enum class TimeSigType : unsigned char;
      54              : struct ClefTypeList;
      55              : }
      56              : 
      57              : namespace mu::iex::mei {
      58              : class UIDRegister;
      59              : 
      60              : struct ControlElementPosition {
      61              :     engraving::Measure* measure = nullptr;
      62              :     engraving::Fraction tick;
      63              :     engraving::track_idx_t track = 0;
      64              :     engraving::ChordRest* chordRest = nullptr;
      65              : };
      66              : 
      67              : enum GraceReading {
      68              :     GraceNone = 0,
      69              :     GraceAsGrp,
      70              :     GraceAsNote
      71              : };
      72              : 
      73              : /**
      74              :  * Class of importing Music Encoding Initiative (MEI) files
      75              :  */
      76              : 
      77              : class MeiImporter
      78              : {
      79              :     muse::GlobalInject<mu::iex::mei::IMeiConfiguration> configuration;
      80              :     muse::GlobalInject<muse::io::IFileSystem> fileSystem;
      81              : 
      82              : public:
      83           64 :     MeiImporter(engraving::Score* s) { m_score = s; }
      84              :     bool read(const muse::io::path_t& path);
      85              : 
      86              : private:
      87              :     /**
      88              :      * Methods for parsing the MEI tree and converting data
      89              :      */
      90              :     bool readMeiHead(pugi::xml_node root);
      91              :     bool readScore(pugi::xml_node root);
      92              :     bool readScoreDef(pugi::xml_node scoreDefNode, bool isInitial);
      93              :     bool readPgHead(pugi::xml_node pgHeadNode);
      94              :     bool readLines(pugi::xml_node parentNode, muse::StringList& lines, size_t& line);
      95              :     bool readLinesWithSmufl(pugi::xml_node parentNode, muse::StringList& lines);
      96              :     bool readStaffDefs(pugi::xml_node parentNode);
      97              :     bool readStaffGrps(pugi::xml_node parentNode, int& staffSpan, int column, size_t& idx);
      98              :     bool readInstrDef(pugi::xml_node instrDefNode, engraving::Part* part);
      99              :     bool readSectionElements(pugi::xml_node parentNode);
     100              :     bool readEnding(pugi::xml_node endingNode);
     101              :     bool readMeasure(pugi::xml_node measureNode);
     102              :     bool readPb(pugi::xml_node pbNode);
     103              :     bool readSb(pugi::xml_node sbNode);
     104              :     bool readStaves(pugi::xml_node parentNode, engraving::Measure* measure, engraving::Fraction& measureTicks);
     105              :     bool readLayers(pugi::xml_node parentNode, engraving::Measure* measure, int staffIdx, engraving::Fraction& measureTicks);
     106              : 
     107              :     /**
     108              :      * Methods for parsing MEI elements within a <layer>
     109              :      */
     110              :     bool readElements(pugi::xml_node parentNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
     111              :     bool readArtics(pugi::xml_node parentNode, engraving::Chord* chord);
     112              :     bool readArtic(pugi::xml_node articNode, engraving::Chord* chord);
     113              :     bool readArtic(pugi::xml_node articNode, engraving::Note* note);
     114              :     bool readBeam(pugi::xml_node beamNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
     115              :     bool readBTrem(pugi::xml_node bTremNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
     116              :     bool readClef(pugi::xml_node clefNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
     117              :     bool readChord(pugi::xml_node chordNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
     118              :     bool readFTrem(pugi::xml_node fTremNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
     119              :     bool readGraceGrp(pugi::xml_node graceGrpNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
     120              :     bool readMRest(pugi::xml_node mRestNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
     121              :     bool readMRpt(pugi::xml_node mRptNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
     122              :     bool readNote(pugi::xml_node noteNode, engraving::Measure* measure, int track, engraving::Fraction& ticks,
     123              :                   engraving::Chord* chord = nullptr);
     124              :     bool readRest(pugi::xml_node restNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
     125              :     bool readSpace(pugi::xml_node spaceNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
     126              :     bool readSyl(pugi::xml_node sylNode, engraving::Lyrics* lyrics, Convert::textWithSmufl& textBlocks, ElisionType elision);
     127              :     bool readTuplet(pugi::xml_node tupletNode, engraving::Measure* measure, int track, engraving::Fraction& ticks);
     128              :     bool readVerses(pugi::xml_node parentNode, engraving::Chord* chord);
     129              :     bool readVerse(pugi::xml_node verseNode, engraving::Chord* chord);
     130              : 
     131              :     /**
     132              :      * Methods for parsing MEI control events (within <measure>)
     133              :      */
     134              :     bool readControlEvents(pugi::xml_node parentNode, engraving::Measure* measure);
     135              :     bool readArpeg(pugi::xml_node arpegNode, engraving::Measure* measure);
     136              :     bool readBreath(pugi::xml_node breathNode, engraving::Measure* measure);
     137              :     bool readCaesura(pugi::xml_node caesuraNode, engraving::Measure* measure);
     138              :     bool readDir(pugi::xml_node dirNote, engraving::Measure* measure);
     139              :     bool readDynam(pugi::xml_node dynamNode, engraving::Measure* measure);
     140              :     bool readF(pugi::xml_node fNode, engraving::FiguredBass* figuredBass);
     141              :     bool readFb(pugi::xml_node harmNode, engraving::Measure* measure);
     142              :     bool readFermata(pugi::xml_node fermataNode, engraving::Measure* measure);
     143              :     bool readFing(pugi::xml_node fingNode, engraving::Measure* measure);
     144              :     bool readGliss(pugi::xml_node glissNode, engraving::Measure* measure);
     145              :     bool readHairpin(pugi::xml_node hairpinNode, engraving::Measure* measure);
     146              :     bool readHarm(pugi::xml_node harmNode, engraving::Measure* measure);
     147              :     bool readHarpPedal(pugi::xml_node harpPedalNode, engraving::Measure* measure);
     148              :     bool readLv(pugi::xml_node lvNode, engraving::Measure* measure);
     149              :     bool readMordent(pugi::xml_node mordentNode, engraving::Measure* measure);
     150              :     bool readOctave(pugi::xml_node octaveNode, engraving::Measure* measure);
     151              :     bool readOrnam(pugi::xml_node ornamNode, engraving::Measure* measure);
     152              :     bool readPedal(pugi::xml_node pedalNode, engraving::Measure* measure);
     153              :     bool readReh(pugi::xml_node rehNode, engraving::Measure* measure);
     154              :     bool readRepeatMark(pugi::xml_node repeatMarkNode, engraving::Measure* measure);
     155              :     bool readSlur(pugi::xml_node slurNode, engraving::Measure* measure);
     156              :     bool readTempo(pugi::xml_node tempoNode, engraving::Measure* measure);
     157              :     bool readTie(pugi::xml_node tieNode, engraving::Measure* measure);
     158              :     bool readTrill(pugi::xml_node trillNode, engraving::Measure* measure);
     159              :     bool readTurn(pugi::xml_node turnNode, engraving::Measure* measure);
     160              : 
     161              :     /**
     162              :      * Methods for parsing specific MEI attribute classes within elements
     163              :      */
     164              :     bool readGracedAtt(libmei::AttGraced& gracedAtt);
     165              :     bool readStemsAtt(engraving::Chord* chord, libmei::AttStems& stemsAtt);
     166              : 
     167              :     /**
     168              :      * Methods for extracting content from the MEI
     169              :      */
     170              :     bool buildIdMap(pugi::xml_node scoreNode);
     171              :     bool buildStaffLayerMap(pugi::xml_node root);
     172              :     bool buildTextFrame();
     173              :     bool buildScoreParts(pugi::xml_node scoreDefNode);
     174              : 
     175              :     /**
     176              :      * Helper methods for content creation
     177              :      */
     178              :     void addEndBarLineToMeasure(engraving::Measure* measure, engraving::BarLineType barLineType);
     179              :     void addLayoutBreakToMeasure(engraving::Measure* measure, engraving::LayoutBreakType layoutBreakType);
     180              :     void addTextToTitleFrame(engraving::VBox*& vBox, const muse::String& str, engraving::TextStyleType textStyleType);
     181              :     void addSpannerEnds();
     182              : 
     183              :     /**
     184              :      * Helper methods
     185              :      */
     186              :     int getStaffIndex(int staffN);
     187              :     int getVoiceIndex(int staffIdx, int layerN);
     188              :     void addLog(const std::string& msg, pugi::xml_node node);
     189              :     bool isNode(pugi::xml_node node, const muse::String& name);
     190              :     engraving::ChordRest* addChordRest(pugi::xml_node node, engraving::Measure* measure, int track, const libmei::Element& meiElement,
     191              :                                        engraving::Fraction& ticks, bool isRest);
     192              :     bool addGraceNotesToChord(engraving::ChordRest* chordRest, bool isAfter = false);
     193              :     engraving::EngravingItem* addAnnotation(const libmei::Element& meiElement, engraving::Measure* measure);
     194              :     engraving::Spanner* addSpanner(const libmei::Element& meiElement, engraving::Measure* measure, pugi::xml_node node);
     195              :     engraving::EngravingItem* addToChordRest(const libmei::Element& meiElement, engraving::Measure* measure,
     196              :                                              engraving::Chord* chord = nullptr);
     197              :     std::string xmlIdFrom(std::string dataURI);
     198              :     ControlElementPosition findStart(const libmei::Element& meiElement, engraving::Measure* measure);
     199              :     ControlElementPosition findEnd(pugi::xml_node controlNode, engraving::Spanner* spanner);
     200              :     engraving::Note* findStartNote(const libmei::Element& meiElement);
     201              :     engraving::Note* findEndNote(pugi::xml_node controlNode);
     202              :     const std::vector<engraving::ChordRest*> findPlistChordRests(pugi::xml_node controlNode);
     203              :     void clearGraceNotes();
     204              :     bool hasLyricsToExtend(engraving::track_idx_t track, int no);
     205              :     const std::pair<engraving::Lyrics*, engraving::ChordRest*>& getLyricsToExtend(engraving::track_idx_t track, int no);
     206              :     void addChordtoLyricsToExtend(engraving::ChordRest* chordRest);
     207              :     void extendLyrics(const std::pair<engraving::Lyrics*, engraving::ChordRest*>& lyricsToExtend);
     208              :     void extendLyrics();
     209              :     void setOrnamentAccid(engraving::Ornament* ornament, const Convert::OrnamStruct& ornamSt);
     210              : 
     211              :     /** Read the xmlId and process it appropriately */
     212              :     void readXmlId(engraving::EngravingItem* item, const std::string& meiUID);
     213              : 
     214              :     /** The Score pointer */
     215              :     engraving::Score* m_score = nullptr;
     216              : 
     217              :     /** The uid register */
     218              :     UIDRegister* m_uids;
     219              : 
     220              :     /** A flag indicating the file has MuseScore EIDs as xml:ids */
     221              :     bool m_hasMuseScoreIds;
     222              : 
     223              :     engraving::Fraction m_ticks;
     224              :     int m_lastMeasureN;
     225              :     engraving::Measure* m_lastMeasure;
     226              : 
     227              :     /** map of MuseScore indexes and clef, timesig and keysig */
     228              :     std::map<int, engraving::ClefTypeList> m_clefs;
     229              :     std::map<int, std::pair<engraving::Fraction, engraving::TimeSigType> > m_timeSigs;
     230              :     std::map<int, engraving::Key> m_keySigs;
     231              :     /** the current time signature */
     232              :     engraving::Fraction m_currentTimeSig = engraving::Fraction(4, 4);
     233              : 
     234              :     /* Set for mapping between MEI staff@n and MuseScore staff indexes */
     235              :     std::set<int> m_staffNs;
     236              :     /* A map of sets for mapping between MEI layer@ in MuseScore voice indexes */
     237              :     std::map<int, std::set<int> > m_staffLayerNs;
     238              :     /* A map for original staffN and MuseScore parts */
     239              :     std::map<int, engraving::Part*> m_staffParts;
     240              : 
     241              :     /* A map for startId and corresponding engraving::ChordRest */
     242              :     std::map<std::string, engraving::ChordRest*> m_startIdChordRests;
     243              :     /* A map for endId and corresponding engraving::ChordRest */
     244              :     std::map<std::string, engraving::ChordRest*> m_endIdChordRests;
     245              :     /* A map for startId and corresponding engraving::Note */
     246              :     std::map<std::string, engraving::Note*> m_startIdNotes;
     247              :     /* A map for endId and corresponding engraving::Note */
     248              :     std::map<std::string, engraving::Note*> m_endIdNotes;
     249              :     /* A map for plist values and corresponding engraving::ChordRest */
     250              :     std::map<std::string, engraving::ChordRest*> m_plistValueChordRests;
     251              :     /* A map for open spanners that needs to be ended */
     252              :     std::map<engraving::Spanner*, pugi::xml_node> m_openSpannerMap;
     253              :     /* A map for open arpeg that needs to be spanned */
     254              :     std::map<engraving::Arpeggio*, pugi::xml_node> m_openArpegMap;
     255              : 
     256              :     /** A map of a map for lyrics with extender that needs to be extended */
     257              :     std::map<engraving::track_idx_t, std::map<int, std::pair<engraving::Lyrics*, engraving::ChordRest*> > > m_lyricExtenders;
     258              : 
     259              :     engraving::Tuplet* m_tuplet;
     260              :     engraving::BeamMode m_beamBeginMode;
     261              :     engraving::BeamMode m_graceBeamBeginMode;
     262              :     engraving::Chord* m_lastChord;
     263              :     std::string m_tremoloId;
     264              :     engraving::TremoloType m_tremoloType;
     265              : 
     266              :     std::list<engraving::Chord*> m_graceNotes;
     267              :     GraceReading m_readingGraceNotes;
     268              :     engraving::NoteType m_graceNoteType;
     269              : 
     270              :     bool m_readingEnding;
     271              :     engraving::Measure* m_endingStart;
     272              :     engraving::Measure* m_endingEnd;
     273              : };
     274              : } // namespace
        

Generated by: LCOV version 2.0-1