Skip to content

MNX import/export changes for schema version 19#33958

Open
rpatters1 wants to merge 28 commits into
musescore:mainfrom
rpatters1:mnx-schema-19
Open

MNX import/export changes for schema version 19#33958
rpatters1 wants to merge 28 commits into
musescore:mainfrom
rpatters1:mnx-schema-19

Conversation

@rpatters1

Copy link
Copy Markdown
Contributor

This PR depends on #33236. If this PR is merged first, then that one (MNX schema 15) should be closed without merging.

In addition to all the changes for schema 15, this PR contains the following.

  • MNX dynamics support. This is what schema 19 introduced.

  • Bug fixes.

    • Use Beams to calculate overridden stem directions for notes in beams.
    • Fix incorrect calculation of diatonicDelta in export.
  • Add provenance information, which was added to the current mnxdom.

  • Add comprehensive testing of dynamics and other bug fixes.

  • I signed the CLA as username:

  • The title of the PR describes the problem it addresses.

  • Each commit's message describes its purpose and effects, and references the issue it resolves. If changes are extensive, there is a sequence of easily reviewable commits.

  • The code in the PR follows the coding rules.

  • I understand all aspects of the code I'm contributing and I'm able to explain it if requested.

  • The code compiles and runs on my machine, preferably after each commit individually. I have manually tested and verified that my changes fulfil their intended purpose.

  • No prior attempts to resolve this problem exist, or if they do, I listed them in my PR description and described how I avoided repeating past mistakes.

  • There are no unnecessary changes.

  • I created a unit test or vtest to verify the changes I made (if applicable).

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c7604654-1ba4-4bf7-8803-4fab7575233f

📥 Commits

Reviewing files that changed from the base of the PR and between 01163c7 and b4fbaac.

📒 Files selected for processing (1)
  • SetupConfigure.cmake
💤 Files with no reviewable changes (1)
  • SetupConfigure.cmake

📝 Walkthrough

Walkthrough

The PR updates MNX import and export support for fermatas, bow directions, breath marks, dynamics, arpeggios, slurs, hairpins, ottavas, and beam direction. It adds shared conversion helpers for orientation, placement, fermata symbols, and dynamic types, adjusts MNX exporter/importer sequence handling and metadata population, and updates build configuration. New and revised MNX/MuseScore fixtures were added for the covered musical cases.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 48.60% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and clearly summarizes the schema-19 MNX import/export update.
Description check ✅ Passed The description includes the dependency, change summary, and completed checklist items expected by the template.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Linked repositories: Public OSS repositories can only analyze public repositories installed in this organization. No linked repositories were analyzed; skipped musescore/muse_framework.git.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/importexport/mnx/CMakeLists.txt`:
- Line 22: The system mnxdom fallback is not gated to the same API/schema level
as the pinned Git commit, so older installed versions can be selected and then
fail on missing schema-19 symbols. Update the `MSS_USE_SYSTEM_MNXDOM` path in
`src/importexport/mnx/CMakeLists.txt` around `pkg_check_modules` to require an
explicit minimum version or add a configure-time feature check for the needed
mnx types such as `mnx::DynamicValue` and `mnx::FermataSymbol`, so only
compatible system packages are accepted.

In `@src/importexport/mnx/internal/export/mnxexportparts.cpp`:
- Around line 496-499: The ottava-end handling in `MnxExportParts::...` is still
calling `toChord(ottava->endElement())` unconditionally, which can trip the
cast/assert path for rest or other non-chord endpoints. Update this branch to
first check `ottava->endElement()->isChord()` and only then cast to `Chord` and
inspect `graceNotesBefore()`, keeping the existing grace-index adjustment logic
for valid chord endpoints.
- Around line 344-350: The slur export path in mnxexportparts.cpp only verifies
endCR is non-null, but it can still point to a chord/rest that was skipped
during MNX export. In the logic around findFirstChordRest(), mnxEventFromCR(),
and ensure_slurs(), add a validation step that confirms the end chord/rest has a
corresponding MNX event before appending endCR->eid() as the slur target, and
skip emitting the reference if no exported event exists.

In `@src/importexport/mnx/internal/import/mnximporter.cpp`:
- Around line 846-848: The fermata import path in mnximporter.cpp uses
Measure::getSegment for the EndBarLine case, which only returns an existing
segment and can leave addFermata with null when no explicit barline was created.
Update the fermata handling in the MNX measure import flow to use the same
creating relative lookup as the barline path, ensuring the EndBarLine segment is
created before calling addFermata. Keep the fix localized around
mnxMeasure.fermata(), measure, and addFermata so the global fermata is always
attached correctly.

In `@src/importexport/mnx/internal/import/mnximportpartmeasures.cpp`:
- Around line 1229-1236: Filter sequences by the resolved staff before applying
the voice offset in mnximportpartmeasures::importPartMeasures. The current loop
over mnxMeasure.sequences() uses x as a global sequence index, but curTrackIdx
+= x should only use the offset among sequences belonging to the same staff as
the dynamic. Update the mnxDynamic.voice() handling to first restrict to
sequences for the target staff, then apply the voice match and offset so
multi-staff parts map to the correct MuseScore voice.

In `@src/importexport/mnx/internal/shared/mnxtypesconv.cpp`:
- Around line 761-769: The mnx::Orientation::Auto branch in
toMuseScorePlacementV assumes item is always non-null and dereferences it
directly, so make that contract explicit by either changing the parameter to a
reference if every caller must provide an EngravingItem, or adding a null
check/assert with a safe fallback before accessing
propertyDefault(Pid::PLACEMENT). Keep the fix localized in toMuseScorePlacementV
and update any callers if the signature changes.

In `@src/importexport/mnx/internal/shared/mnxtypesconv.h`:
- Line 25: The mnxtypesconv.h header uses std::pair in its public API, but it
does not include the defining header directly. Add the appropriate include for
std::pair in this header so it is self-contained, and keep the existing
declarations that expose std::pair unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 6bb7451d-ffe9-4e06-a63f-0445ab40c0e7

📥 Commits

Reviewing files that changed from the base of the PR and between ef2d70a and a3a7a3c.

📒 Files selected for processing (46)
  • src/importexport/mnx/CMakeLists.txt
  • src/importexport/mnx/internal/export/mnxexporter.cpp
  • src/importexport/mnx/internal/export/mnxexporter.h
  • src/importexport/mnx/internal/export/mnxexportglobal.cpp
  • src/importexport/mnx/internal/export/mnxexportlayouts.cpp
  • src/importexport/mnx/internal/export/mnxexportparts.cpp
  • src/importexport/mnx/internal/export/mnxexportsequences.cpp
  • src/importexport/mnx/internal/import/mnximporter.cpp
  • src/importexport/mnx/internal/import/mnximporter.h
  • src/importexport/mnx/internal/import/mnximportmarkings.cpp
  • src/importexport/mnx/internal/import/mnximportpartmeasures.cpp
  • src/importexport/mnx/internal/shared/mnxtypesconv.cpp
  • src/importexport/mnx/internal/shared/mnxtypesconv.h
  • src/importexport/mnx/tests/data/README.md
  • src/importexport/mnx/tests/data/mscx_reference_examples/dynamics_ref.mscx
  • src/importexport/mnx/tests/data/project_examples/arpeggios.mnx
  • src/importexport/mnx/tests/data/project_examples/arpeggios_ref.mscx
  • src/importexport/mnx/tests/data/project_examples/beamsOverBarlines_ref.mscx
  • src/importexport/mnx/tests/data/project_examples/bowDirection.mnx
  • src/importexport/mnx/tests/data/project_examples/bowDirection_ref.mscx
  • src/importexport/mnx/tests/data/project_examples/breathMark.mnx
  • src/importexport/mnx/tests/data/project_examples/breathMark_ref.mscx
  • src/importexport/mnx/tests/data/project_examples/dynamicV1V2.mnx
  • src/importexport/mnx/tests/data/project_examples/dynamicV1V2_ref.mscx
  • src/importexport/mnx/tests/data/project_examples/dynamicVoice.mnx
  • src/importexport/mnx/tests/data/project_examples/dynamicVoice_ref.mscx
  • src/importexport/mnx/tests/data/project_examples/dynamicsHairpins.mnx
  • src/importexport/mnx/tests/data/project_examples/dynamicsHairpins_ref.mscx
  • src/importexport/mnx/tests/data/project_examples/enharmonics.mnx
  • src/importexport/mnx/tests/data/project_examples/enharmonics_ref.mscx
  • src/importexport/mnx/tests/data/project_examples/fermata.mnx
  • src/importexport/mnx/tests/data/project_examples/fermata_ref.mscx
  • src/importexport/mnx/tests/data/project_examples/graceArps.mnx
  • src/importexport/mnx/tests/data/project_examples/graceArps_ref.mscx
  • src/importexport/mnx/tests/data/project_examples/nonArpeggios.mnx
  • src/importexport/mnx/tests/data/project_examples/nonArpeggios_ref.mscx
  • src/importexport/mnx/tests/data/project_sources/arpeggios.enigmaxml
  • src/importexport/mnx/tests/data/project_sources/bowDirection.enigmaxml
  • src/importexport/mnx/tests/data/project_sources/breathMark.enigmaxml
  • src/importexport/mnx/tests/data/project_sources/dynamicV1V2.enigmaxml
  • src/importexport/mnx/tests/data/project_sources/dynamicVoice.enigmaxml
  • src/importexport/mnx/tests/data/project_sources/dynamicsHairpins.enigmaxml
  • src/importexport/mnx/tests/data/project_sources/fermata.enigmaxml
  • src/importexport/mnx/tests/data/project_sources/graceArps.enigmaxml
  • src/importexport/mnx/tests/data/project_sources/nonArpeggios.enigmaxml
  • src/importexport/mnx/tests/mnx_tests.cpp

Comment thread src/importexport/mnx/CMakeLists.txt Outdated
mnxdom
GIT_REPOSITORY https://github.com/rpatters1/mnxdom.git
GIT_TAG e7c947bf768caccf315426dcae0dfac02caf738b
GIT_TAG 11a12e6a2492ca54183acf5b22a288dae032c625

@coderabbitai coderabbitai Bot Jun 25, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify whether the system mnxdom path enforces a version/API gate.
rg -n 'pkg_check_modules\(mnxdom|MSS_USE_SYSTEM_MNXDOM|DynamicValue|FermataSymbol' src/importexport/mnx

Repository: musescore/MuseScore

Length of output: 10190


Gate system mnxdom to the same schema/API level as the pinned commit.

The Git-fetched mnxdom is pinned to a commit supporting schema-19 types (e.g., mnx::DynamicValue, mnx::FermataSymbol), but enabling MSS_USE_SYSTEM_MNXDOM relies on an unconstrained pkg_check_modules call. Older system versions lack these types, causing compilation failures.

Enforce a minimum version in pkg_check_modules or add a configure-time check for the required types.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/importexport/mnx/CMakeLists.txt` at line 22, The system mnxdom fallback
is not gated to the same API/schema level as the pinned Git commit, so older
installed versions can be selected and then fail on missing schema-19 symbols.
Update the `MSS_USE_SYSTEM_MNXDOM` path in `src/importexport/mnx/CMakeLists.txt`
around `pkg_check_modules` to require an explicit minimum version or add a
configure-time feature check for the needed mnx types such as
`mnx::DynamicValue` and `mnx::FermataSymbol`, so only compatible system packages
are accepted.

@rpatters1 rpatters1 Jun 25, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can't be resolved with the current build approach. We need to get this merged, and then I will refactor the build using a submodule, so that there will no longer be a need to use a system version of the mnxdom.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rpatters1 Understood — thanks for the clarification. Given the planned follow-up to switch mnxdom handling to a submodule and remove the system-installed path, I won’t push further on this in the current PR.

If you want, I can open a follow-up GitHub issue to track that build refactor separately. I’ve also noted this context for future reviews.

(•ᴗ•)🐇


🧠 Learnings used
Learnt from: igorkorsukov
Repo: musescore/MuseScore PR: 33517
File: CMakeLists.txt:52-56
Timestamp: 2026-05-21T09:19:10.076Z
Learning: In the MuseScore (musescore/MuseScore) repo, the CMake modules like `CheckCompilerVersion`, `GetCompilerInfo`, `SetupBuildEnvironment`, `GetPlatformInfo`, `SetupCompilerCache`, `SetupCompileWarnings`, `SetupQt6`, `GetUtilsFunctions`, etc. come from the `muse` git submodule under `muse/` (framework sources in `muse/framework/`). In environments that don’t clone submodules (e.g., the sandbox), searches for these module files may return empty results—this is expected and should not be flagged as a bug. When reviewing CMake, expect `${MUSE_FRAMEWORK_PATH}/buildscripts/cmake` to be added to `CMAKE_MODULE_PATH` so these modules are discoverable during normal builds.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, open an issue and assign me it.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="musescore/MuseScore"
assignee="rpatters1"

body_file="$(mktemp)"
cat > "$body_file" <<'EOF'
## Summary
Refactor the MNX build integration to stop relying on the optional system-installed `mnxdom` path and instead use a repository-managed dependency flow (planned submodule-based approach).

## Background
In `#33958`, the fetched `mnxdom` revision was updated to a newer upstream commit to support the schema/API surface now required by the MNX import/export code. The current `MSS_USE_SYSTEM_MNXDOM` path in `src/importexport/mnx/CMakeLists.txt` does not enforce compatibility with that same API level, but this cannot be cleanly resolved within the current build approach.

Per the PR discussion, the intended follow-up is to refactor the build so that `mnxdom` is handled via a submodule and the need for a system-installed fallback is removed.

## Affected area
- `src/importexport/mnx/CMakeLists.txt`
- MNX build/dependency wiring for `iex_mnx`

## Requested changes
- Refactor `mnxdom` integration to use the planned submodule-based build approach.
- Remove or otherwise retire the `MSS_USE_SYSTEM_MNXDOM` path if it is no longer needed.
- Ensure the build uses a single controlled `mnxdom` source that matches the API/schema requirements of the MNX import/export code.

## Rationale
This avoids configuration-time ambiguity where a system package may not match the API level expected by the source tree, and it aligns dependency resolution with the intended long-term build structure.

## Acceptance criteria
- `iex_mnx` no longer depends on an unconstrained system `mnxdom` package path.
- The build configuration documents and uses the repository-managed `mnxdom` dependency flow.
- MNX import/export code builds against the intended `mnxdom` revision/API surface without needing separate system-package compatibility handling.

## Backlinks
- PR: https://github.com/musescore/MuseScore/pull/33958
- Review comment: https://github.com/musescore/MuseScore/pull/33958#discussion_r3475542228

Requested by: `@rpatters1`
EOF

issue_url="$(gh issue create \
  --repo "$repo" \
  --title "Refactor MNX build to use submodule-managed mnxdom and remove system fallback" \
  --body-file "$body_file" \
  --assignee "$assignee")"

echo "CREATED_ISSUE_URL=$issue_url"

Length of output: 2712


🏁 Script executed:

#!/bin/bash
set -euo pipefail

repo="musescore/MuseScore"

body_file="$(mktemp)"
cat > "$body_file" <<'EOF'
## Summary
Refactor the MNX build integration to stop relying on the optional system-installed `mnxdom` path and instead use a repository-managed dependency flow (planned submodule-based approach).

## Background
In `#33958`, the fetched `mnxdom` revision was updated to a newer upstream commit to support the schema/API surface now required by the MNX import/export code. The current `MSS_USE_SYSTEM_MNXDOM` path in `src/importexport/mnx/CMakeLists.txt` does not enforce compatibility with that same API level, but this cannot be cleanly resolved within the current build approach.

Per the PR discussion, the intended follow-up is to refactor the build so that `mnxdom` is handled via a submodule and the need for a system-installed fallback is removed.

## Affected area
- `src/importexport/mnx/CMakeLists.txt`
- MNX build/dependency wiring for `iex_mnx`

## Requested changes
- Refactor `mnxdom` integration to use the planned submodule-based build approach.
- Remove or otherwise retire the `MSS_USE_SYSTEM_MNXDOM` path if it is no longer needed.
- Ensure the build uses a single controlled `mnxdom` source that matches the API/schema requirements of the MNX import/export code.

## Rationale
This avoids configuration-time ambiguity where a system package may not match the API level expected by the source tree, and it aligns dependency resolution with the intended long-term build structure.

## Acceptance criteria
- `iex_mnx` no longer depends on an unconstrained system `mnxdom` package path.
- The build configuration documents and uses the repository-managed `mnxdom` dependency flow.
- MNX import/export code builds against the intended `mnxdom` revision/API surface without needing separate system-package compatibility handling.

## Backlinks
- PR: https://github.com/musescore/MuseScore/pull/33958
- Review comment: https://github.com/musescore/MuseScore/pull/33958#discussion_r3475542228

Requested by: `@rpatters1`
Note: assignment to `@rpatters1` was requested in the PR discussion, but may need to be applied manually if the integration lacks assignee permissions.
EOF

issue_url="$(gh issue create \
  --repo "$repo" \
  --title "Refactor MNX build to use submodule-managed mnxdom and remove system fallback" \
  --body-file "$body_file")"

echo "CREATED_ISSUE_URL=$issue_url"

Length of output: 2609



@rpatters1 Opened the follow-up issue: #33966

#33966

I also tried to assign it to you, but the current GitHub integration does not have assignee permissions (Resource not accessible by integration), so that part will need to be done manually.


🧠 Learnings used
Learnt from: igorkorsukov
Repo: musescore/MuseScore PR: 33517
File: CMakeLists.txt:52-56
Timestamp: 2026-05-21T09:19:10.076Z
Learning: In the MuseScore (musescore/MuseScore) repo, the CMake modules like `CheckCompilerVersion`, `GetCompilerInfo`, `SetupBuildEnvironment`, `GetPlatformInfo`, `SetupCompilerCache`, `SetupCompileWarnings`, `SetupQt6`, `GetUtilsFunctions`, etc. come from the `muse` git submodule under `muse/` (framework sources in `muse/framework/`). In environments that don’t clone submodules (e.g., the sandbox), searches for these module files may return empty results—this is expected and should not be flagged as a bug. When reviewing CMake, expect `${MUSE_FRAMEWORK_PATH}/buildscripts/cmake` to be added to `CMAKE_MODULE_PATH` so these modules are discoverable during normal builds.

Comment thread src/importexport/mnx/internal/export/mnxexportparts.cpp
Comment thread src/importexport/mnx/internal/export/mnxexportparts.cpp
Comment thread src/importexport/mnx/internal/import/mnximporter.cpp
Comment thread src/importexport/mnx/internal/import/mnximportpartmeasures.cpp Outdated
Comment thread src/importexport/mnx/internal/shared/mnxtypesconv.cpp
Comment thread src/importexport/mnx/internal/shared/mnxtypesconv.h
@Jojo-Schmitz

Jojo-Schmitz commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

I wonder whether a rebase fixes the (vtest) build failure?

@rpatters1

Copy link
Copy Markdown
Contributor Author

I winder whether a rebase fixes the (vtest) build faulure?

Considering the failure is nowhere near the mnx code, Imma go with yes.

rpatters1 added 24 commits July 9, 2026 09:16
- fix typo in log message
- clean up breathMark test case for more complete coverage
… beam direction)

Add more tests for voiced dynamics
…th voice assignments on imports. This commit fixes that.
rpatters1 added 3 commits July 9, 2026 09:42
- wrap import in transaction to suppress undo warning
- suppress undo warnings in text fixture
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.

3 participants