Repository: musescore/MuseScore
Pull request #27839: Fix import of 1.x jumps and markers
Author: login: Jojo-Schmitz
Created: 2025-04-25T09:03:30Z | Merged: 2025-04-25T13:07:51Z

Resolves: #27832


Diff:
diff --git a/src/engraving/rw/read114/read114.cpp b/src/engraving/rw/read114/read114.cpp
index 47ffd4a639213..7c039604a51a9 100644
--- a/src/engraving/rw/read114/read114.cpp
+++ b/src/engraving/rw/read114/read114.cpp
@@ -2000,14 +2000,34 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e, ReadContext& ctx
                     j->setPlayUntil(e.readText());
                 } else if (t == "continueAt") {
                     j->setContinueAt(e.readText());
-                } else if (t == "playRepeats") {
-                    j->setPlayRepeats(e.readBool());
                 } else if (t == "subtype") {
-                    e.readInt();
+                    e.skipCurrentElement(); // obsolete, always "Repeat"
                 } else if (!TRead::readTextProperties(j, e, ctx)) {
                     e.unknown();
                 }
             }
+
+            // infer jump type
+            String jumpTo = j->jumpTo();
+            String playUntil = j->playUntil();
+            if (jumpTo == "start") {
+                if (playUntil == "end") {
+                    j->setJumpType(JumpType::DC);
+                } else if (playUntil == "fine") {
+                    j->setJumpType(JumpType::DC_AL_FINE);
+                } else {
+                    j->setJumpType(JumpType::DC_AL_CODA);
+                }
+            } else {
+                if (playUntil == "end") {
+                    j->setJumpType(JumpType::DS);
+                } else if (playUntil == "fine") {
+                    j->setJumpType(JumpType::DS_AL_FINE);
+                } else {
+                    j->setJumpType(JumpType::DS_AL_CODA);
+                }
+            }
+
             m->add(j);
         } else if (tag == "Marker") {
             Marker* a = Factory::createMarker(m);
@@ -2016,7 +2036,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e, ReadContext& ctx
             MarkerType mt = MarkerType::SEGNO;
             while (e.readNextStartElement()) {
                 const AsciiStringView t(e.name());
-                if (t == "subtype") {
+                if (t == "subtype" || t == "label") {
                     AsciiStringView s(e.readAsciiText());
                     a->setLabel(String::fromAscii(s.ascii()));
                     mt = TConv::fromXml(s, MarkerType::USER);
@@ -2031,6 +2051,7 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e, ReadContext& ctx
                 // force the marker type for correct display
                 a->setXmlText(u"");
                 a->setMarkerType(a->markerType());
+                a->setTextStyleType(TextStyleType::REPEAT_LEFT);
             }
             m->add(a);
         } else if (tag == "Image") {
diff --git a/src/engraving/tests/compat114_data/markers-ref.mscx b/src/engraving/tests/compat114_data/markers-ref.mscx
index bf4c6bd16c2ed..512a6a797e5b9 100644
--- a/src/engraving/tests/compat114_data/markers-ref.mscx
+++ b/src/engraving/tests/compat114_data/markers-ref.mscx
@@ -74,9 +74,9 @@
     <Staff id="1">
       <Measure>
         <Marker>
-          <style>repeat_right</style>
-          <text>To Coda</text>
-          <label>coda</label>
+          <style>repeat_left</style>
+          <text><sym>segno</sym></text>
+          <label>segno</label>
           </Marker>
         <voice>
           <Clef>
@@ -99,9 +99,9 @@
         </Measure>
       <Measure>
         <Marker>
-          <style>repeat_right</style>
-          <text>To Coda</text>
-          <label>coda</label>
+          <style>repeat_left</style>
+          <text><sym>coda</sym></text>
+          <label>codab</label>
           </Marker>
         <voice>
           <Rest>
@@ -112,9 +112,9 @@
         </Measure>
       <Measure>
         <Marker>
-          <style>repeat_right</style>
-          <text>To Coda</text>
-          <label>coda</label>
+          <style>repeat_left</style>
+          <text><sym>codaSquare</sym></text>
+          <label>varcoda</label>
           </Marker>
         <voice>
           <Rest>
@@ -128,9 +128,9 @@
           <subtype>line</subtype>
           </LayoutBreak>
         <Marker>
-          <style>repeat_right</style>
-          <text>To Coda</text>
-          <label>coda</label>
+          <style>repeat_left</style>
+          <text><sym>coda</sym><sym>coda</sym></text>
+          <label>codetta</label>
           </Marker>
         <voice>
           <Rest>
@@ -142,8 +142,8 @@
       <Measure>
         <Marker>
           <style>repeat_right</style>
-          <text>To Coda</text>
-          <label>coda</label>
+          <text>Fine</text>
+          <label>fine</label>
           </Marker>
         <voice>
           <Rest>
@@ -154,8 +154,8 @@
         </Measure>
       <Measure>
         <Jump>
-          <style>staff</style>
-          <text/>
+          <style>repeat_right</style>
+          <text>D.C.</text>
           <jumpTo>start</jumpTo>
           <playUntil>end</playUntil>
           <continueAt></continueAt>
@@ -169,8 +169,8 @@
         </Measure>
       <Measure>
         <Jump>
-          <style>staff</style>
-          <text/>
+          <style>repeat_right</style>
+          <text>D.C. al Fine</text>
           <jumpTo>start</jumpTo>
           <playUntil>fine</playUntil>
           <continueAt></continueAt>
@@ -187,8 +187,8 @@
           <subtype>line</subtype>
           </LayoutBreak>
         <Jump>
-          <style>staff</style>
-          <text/>
+          <style>repeat_right</style>
+          <text>D.C. al Coda</text>
           <jumpTo>start</jumpTo>
           <playUntil>coda</playUntil>
           <continueAt>codab</continueAt>
@@ -202,8 +202,8 @@
         </Measure>
       <Measure>
         <Jump>
-          <style>staff</style>
-          <text/>
+          <style>repeat_right</style>
+          <text>D.S. al Coda</text>
           <jumpTo>segno</jumpTo>
           <playUntil>coda</playUntil>
           <continueAt>codab</continueAt>
@@ -217,8 +217,8 @@
         </Measure>
       <Measure>
         <Jump>
-          <style>staff</style>
-          <text/>
+          <style>repeat_right</style>
+          <text>D.S. al Fine</text>
           <jumpTo>segno</jumpTo>
           <playUntil>fine</playUntil>
           <continueAt></continueAt>
@@ -232,8 +232,8 @@
         </Measure>
       <Measure>
         <Jump>
-          <style>staff</style>
-          <text/>
+          <style>repeat_right</style>
+          <text>D.S.</text>
           <jumpTo>segno</jumpTo>
           <playUntil>end</playUntil>
           <continueAt></continueAt>


Reviews:
user: login: Jojo-Schmitz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T09:08:45Z
user: login: Jojo-Schmitz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T09:11:28Z
user: login: Jojo-Schmitz
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-25T09:11:35Z
user: login: cbjeukendrup
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-25T13:04:05Z

Review comments:
diff_hunk: @@ -2000,14 +2000,41 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e, ReadContext& ctx
                     j->setPlayUntil(e.readText());
                 } else if (t == "continueAt") {
                     j->setContinueAt(e.readText());
-                } else if (t == "playRepeats") {
path: src/engraving/rw/read114/read114.cpp
user: login: Jojo-Schmitz
body: Doesn't exist in Mu1, so removing 'dead code'
created_at: 2025-04-25T09:08:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2000,14 +2000,41 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e, ReadContext& ctx
                     j->setPlayUntil(e.readText());
                 } else if (t == "continueAt") {
                     j->setContinueAt(e.readText());
-                } else if (t == "playRepeats") {
-                    j->setPlayRepeats(e.readBool());
                 } else if (t == "subtype") {
-                    e.readInt();
+                    e.skipCurrentElement(); // obsolete, always "Repeat"
                 } else if (!TRead::readTextProperties(j, e, ctx)) {
                     e.unknown();
                 }
             }
+
+            // infer jump type
+            QString jumpTo = j->jumpTo();
+            QString playUntil = j->playUntil();
+            QString continueAt = j->continueAt();
+            if (jumpTo == "start") {
+                if (playUntil == "end") {
+                    j->setJumpType(JumpType::DC);
+                } else if (playUntil == "fine") {
+                    j->setJumpType(JumpType::DC_AL_FINE);
+                } else if (playUntil == "coda" && continueAt == "codab") {
path: src/engraving/rw/read114/read114.cpp
user: login: Jojo-Schmitz
body: Is this too strict?
Would relaxing (e.g. `playUntil.contains("coda") && continueAt.contains("coda")` or even dropping that check entirely (by making it the `else` branch) also recognize more complex jumps like jumps to a 1st and a 2nd Coda?

At least it wouldn't break the import if a 'regular' D.C. al Coda, and is simpler code... 
created_at: 2025-04-25T09:11:28Z
author_association: CONTRIBUTOR
diff_hunk: @@ -2000,14 +2000,41 @@ static void readMeasure(Measure* m, int staffIdx, XmlReader& e, ReadContext& ctx
                     j->setPlayUntil(e.readText());
                 } else if (t == "continueAt") {
                     j->setContinueAt(e.readText());
-                } else if (t == "playRepeats") {
-                    j->setPlayRepeats(e.readBool());
                 } else if (t == "subtype") {
-                    e.readInt();
+                    e.skipCurrentElement(); // obsolete, always "Repeat"
                 } else if (!TRead::readTextProperties(j, e, ctx)) {
                     e.unknown();
                 }
             }
+
+            // infer jump type
+            QString jumpTo = j->jumpTo();
+            QString playUntil = j->playUntil();
+            QString continueAt = j->continueAt();
+            if (jumpTo == "start") {
+                if (playUntil == "end") {
+                    j->setJumpType(JumpType::DC);
+                } else if (playUntil == "fine") {
+                    j->setJumpType(JumpType::DC_AL_FINE);
+                } else if (playUntil == "coda" && continueAt == "codab") {
+                    j->setJumpType(JumpType::DC_AL_CODA);
+                } else {
+                    j->setJumpType(JumpType::USER);
+                }
+            } else if (jumpTo == "segno") {
+                if (playUntil == "end") {
+                    j->setJumpType(JumpType::DS);
+                } else if (playUntil == "fine") {
+                    j->setJumpType(JumpType::DS_AL_FINE);
+                } else if (playUntil == "coda" && continueAt == "codab") {
path: src/engraving/rw/read114/read114.cpp
user: login: Jojo-Schmitz
body: Is this too strict?
Would relaxing (e.g. `playUntil.contains("coda") && continueAt.contains("coda")` or even dropping that check entirely (by making it the `else` branch) also recognize more complex jumps like jumps to a 1st and a 2nd Coda?

At least it wouldn't break the import if a 'regular' D.S. al Coda, and is simpler code... 
created_at: 2025-04-25T09:11:35Z
author_association: CONTRIBUTOR

PR comments:
user: login: Jojo-Schmitz
created_at: 2025-04-25T10:24:46Z
body: The failing unit test proves my changes to be right! Whoever came up with that ref file was blatantly wrong (or too lazy to fix the issue)...
author_association: CONTRIBUTOR
user: login: Jojo-Schmitz
created_at: 2025-04-25T11:56:01Z
body: Can't help the macOS build failure, it doesn't seem to be my fault at all
author_association: CONTRIBUTOR
user: login: Jojo-Schmitz
created_at: 2025-04-25T12:17:50Z
body: IMHO my work on this is done now... please review
author_association: CONTRIBUTOR