Skip to content

MusicXML: full repeat-ending numbers and display text - #104

Merged
rpatters1 merged 1 commit into
mainfrom
mx-repeat-endings
Aug 6, 2026
Merged

rpatters1 merged 1 commit into
mainfrom
mx-repeat-endings

Conversation

@rpatters1

@rpatters1 rpatters1 commented Aug 6, 2026 •

Copy link
Copy Markdown
Collaborator

Closes the repeat-ending gap. mx replaced BarlineData::endingType and the single int endingNumber with one std::optional<EndingData> carrying the whole pass list and the printed label, so both halves of the Finale ending record can now travel.

Rebased onto main now 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

RepeatPassList is copied whole rather than contributing only values.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 as number="1, 2, 3".

The label

The label comes from RepeatEndingStart::createEndingText(), whose precedence is already the one Finale uses: custom RepeatEndingText verbatim 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 number attribute on its own, which is the pass list joined the way core::EndingNumber::toString joins 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:

denigma Finale
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 1 where Finale draws 1.; 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 the print-style group, 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 /// @todo at the construction site points there.

Dependency pin

mx moves to f52c88e, the head of rpatters1/mx@ending-numbers-and-text, open upstream as webern/mx#388. Verified branch-reachable from the configured repository URL with git ls-remote.

It supersedes 2671b8e rather than building on it: that SHA was the pre-merge form of the harmonic work, and f52c88e carries 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_repository to webern.

Testing

  • full suite from tests/data: 393/393 pass
  • exported both ending fixtures and diffed <ending> output against the checked-in Finale reference exports

🤖 Generated with Claude Code

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
rpatters1 changed the base branch from mx-dynamics-vocabulary to main August 6, 2026 01:37
@rpatters1
rpatters1 merged commit 6030332 into main Aug 6, 2026
3 checks passed
@rpatters1
rpatters1 deleted the mx-repeat-endings branch August 6, 2026 02:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant