Repository navigation
MusicXML: full repeat-ending numbers and display text - #104
Merged
Merged
Conversation
mx replaced BarlineData::endingType and the single int endingNumber with one optional EndingData carrying the whole pass list and the printed label, so both halves of the Finale ending record can now travel. RepeatPassList is copied whole instead of contributing only its first value, and the Info message apologizing for the discarded passes is gone. An ending played on passes 1, 2, and 3 exports as number="1, 2, 3" rather than number="1". The label comes from RepeatEndingStart::createEndingText(), which returns custom RepeatEndingText verbatim when the author set one and otherwise builds the pass list, appending a period when the Add Period repeat option is on. It is assigned only when it differs from the label MusicXML would render from the number attribute on its own, which is the pass list joined the way core::EndingNumber::toString joins it. A document with Add Period on therefore keeps the periods Finale draws, and one without it writes no text node at all. The closing barline repeats the numbers so both barlines identify the same bracket, but never the text, because MusicXML draws a label at every <ending> that carries one. The gap entry for ending display text and multiple numbers is closed. What remains unmappable is the ending's appearance, so the entry is replaced by one covering print-object, end-length, text-x, text-y, system, and the print-style group, each named with the Finale field that would feed it. Hidden endings are the notable loss, since they are structural in Finale rather than decorative. Pins mx to f52c88e, the head of rpatters1/mx@ending-numbers-and-text and open upstream as webern/mx#388. It supersedes 2671b8e, whose dynamics and harmonic work it carries in merged form as webern/mx#382 and #384. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
rpatters1
force-pushed
the
mx-repeat-endings
branch
from
August 6, 2026 01:37
a4df881 to
0aae4e5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the repeat-ending gap. mx replaced
BarlineData::endingTypeand the singleint endingNumberwith onestd::optional<EndingData>carrying the whole pass list and the printed label, so both halves of the Finale ending record can now travel.Rebased onto
mainnow that #103 has landed. That PR is a prerequisite, since the new pin carries mx's dynamics refactor in merged form.All the passes, not just the first
RepeatPassListis copied whole rather than contributing onlyvalues.front(), and the Info message apologizing for the passes it dropped is gone with it. An ending played on passes 1, 2, and 3 exports asnumber="1, 2, 3".The label
The label comes from
RepeatEndingStart::createEndingText(), whose precedence is already the one Finale uses: customRepeatEndingTextverbatim when the author set one, otherwise the pass list, with a period appended per instance when the Add Period repeat option is on. Finale does not add a period to text you typed yourself, and neither does this.It is assigned only when it differs from the label MusicXML renders from the
numberattribute on its own, which is the pass list joined the waycore::EndingNumber::toStringjoins it. So a document with Add Period on keeps the periods Finale draws, a document without it writes no text node at all, and a custom label that happens to read exactly like its numbers is not restated.The closing barline repeats the numbers so that both barlines identify the same bracket, but never the text, because MusicXML draws a label at every
<ending>that carries one.Output against Finale's own export
Both fixtures now match Finale element for element, apart from the appearance attributes below:
repeats.musx, custom text<ending number="1, 2, 3" type="start">1. 2. 3.</ending><ending default-y="40" end-length="30" font-size="8.5" number="1, 2, 3" type="start">1. 2. 3.</ending>repeats.musx, closing<ending number="1, 2, 3" type="stop"/><ending number="1, 2, 3" type="stop"/>tie_target_types.musx, Add Period<ending number="1" type="start">1.</ending><ending ... number="1" print-object="yes" system="only-top" type="start"/>tie_target_types.musx, open ending<ending number="2" type="discontinue"/><ending number="2" type="discontinue"/>The one deliberate divergence is the third row. Finale drops the Add Period label on export, so its own file renders as
1where Finale draws1.; per the spec the text element exists for exactly this case, where the displayed label differs from the number.Gap entry
"Repeat-ending display text and multiple numbers" is closed. What stays unmappable is the ending's appearance, so it is replaced by "Repeat-ending appearance and visibility", covering
print-object,end-length,text-x,text-y,system, and theprint-stylegroup, each named with the Finale field that would feed it. Hidden endings are the notable loss, because they are structural in Finale rather than decorative: the bracket is suppressed while the repeat still governs playback. A/// @todoat the construction site points there.Dependency pin
mx moves to
f52c88e, the head ofrpatters1/mx@ending-numbers-and-text, open upstream as webern/mx#388. Verified branch-reachable from the configured repository URL withgit ls-remote.It supersedes
2671b8erather than building on it: that SHA was the pre-merge form of the harmonic work, andf52c88ecarries both it and the dynamics refactor in their squashed upstream form, webern/mx#384 and #382. When #388 lands it will be squashed again to a new SHA, so this pin needs revisiting then, along with moving_denigma_mx_git_repositoryto webern.Testing
tests/data: 393/393 pass<ending>output against the checked-in Finale reference exports🤖 Generated with Claude Code