From 302bca3c701a761e5aec8161062a4b06183ab3a6 Mon Sep 17 00:00:00 2001 From: Matthew James Briggs Date: Sun, 12 Jul 2026 16:16:49 +0000 Subject: [PATCH] fix: round-trip the metronome parentheses attribute TempoData::isParenthetical existed but dangled: the reader never set it and the writer never emitted it. Wire both sides. Pins the 2 corpus files this flips to PASS (222 total). --- src/private/mx/impl/DirectionWriter.cpp | 5 ++++ src/private/mx/impl/MetronomeReader.cpp | 6 ++++ src/private/mxtest/api/MetronomeApiTest.cpp | 29 +++++++++++++++++++ src/private/mxtest/api/roundtrip-baseline.txt | 5 ++++ 4 files changed, 45 insertions(+) diff --git a/src/private/mx/impl/DirectionWriter.cpp b/src/private/mx/impl/DirectionWriter.cpp index dd3d523f5..79e608691 100644 --- a/src/private/mx/impl/DirectionWriter.cpp +++ b/src/private/mx/impl/DirectionWriter.cpp @@ -469,6 +469,11 @@ void DirectionWriter::emitTempo(const api::TempoData &tempo, core::Direction &di return; } + if (tempo.isParenthetical != api::Bool::unspecified) + { + metronome.setParentheses(myConverter.convert(tempo.isParenthetical)); + } + core::DirectionType dt{}; dt.setChoice(core::DirectionTypeChoice::metronome(metronome)); addDirectionType(std::move(dt), direction); diff --git a/src/private/mx/impl/MetronomeReader.cpp b/src/private/mx/impl/MetronomeReader.cpp index 99eb5fcc2..cc8591dc0 100644 --- a/src/private/mx/impl/MetronomeReader.cpp +++ b/src/private/mx/impl/MetronomeReader.cpp @@ -30,6 +30,12 @@ api::TempoData MetronomeReader::getTempoData() const myOutTempoData = api::TempoData{}; // the old core's beatUnitPer is the new core's group; the old core's // noteRelationNote (metronome-note based) is group2 + if (myMetronome.parentheses().has_value()) + { + Converter converter; + myOutTempoData.isParenthetical = converter.convert(*myMetronome.parentheses()); + } + using FirstChoice = core::MetronomeChoice::Kind; const auto firstChoice = myBeatUnitPerOrNoteRelationNoteChoice.kind(); diff --git a/src/private/mxtest/api/MetronomeApiTest.cpp b/src/private/mxtest/api/MetronomeApiTest.cpp index 5f5c90a31..f83a5a9e7 100644 --- a/src/private/mxtest/api/MetronomeApiTest.cpp +++ b/src/private/mxtest/api/MetronomeApiTest.cpp @@ -201,4 +201,33 @@ TEST(roundTripMetricModulation, MetronomeApi) T_END +TEST(roundTripParentheses, MetronomeApi) +{ + // must round-trip via TempoData::isParenthetical. + ScoreData score; + score.ticksPerQuarter = 100; + score.parts.emplace_back(); + auto &part = score.parts.back(); + part.measures.emplace_back(); + auto &measure = part.measures.back(); + measure.staves.emplace_back(); + auto &staff = measure.staves.back(); + staff.directions.emplace_back(); + auto &direction = staff.directions.back(); + direction.tempos.emplace_back(); + auto &tempo = direction.tempos.back(); + tempo.tempoType = TempoType::beatsPerMinute; + tempo.isParenthetical = Bool::yes; + tempo.beatsPerMinute.durationName = DurationName::quarter; + tempo.beatsPerMinute.beatsPerMinute = 100; + + auto actualScoreData = roundTrip(score); + + const auto &actualTempo = + actualScoreData.parts.back().measures.back().staves.back().directions.back().tempos.back(); + CHECK(actualTempo.isParenthetical == Bool::yes); +} + +T_END + #endif diff --git a/src/private/mxtest/api/roundtrip-baseline.txt b/src/private/mxtest/api/roundtrip-baseline.txt index 70314f431..6626069b0 100644 --- a/src/private/mxtest/api/roundtrip-baseline.txt +++ b/src/private/mxtest/api/roundtrip-baseline.txt @@ -414,3 +414,8 @@ synthetic/non-arpeggiate.3.1.xml ksuite/k001a_Articulations.xml musuite/testNoteAttributes2.xml musuite/testNoteAttributes2_ref.xml + +# Unblocked by wiring TempoData::isParenthetical: the metronome parentheses +# attribute now round-trips. +lysuite/ly31c_MetronomeMarks.xml +musuite/testTempo1.xml