Skip to content

Add native score-to-video sync#33323

Open
ToranadoMusic wants to merge 29 commits into
musescore:mainfrom
ToranadoMusic:score-to-video
Open

Add native score-to-video sync#33323
ToranadoMusic wants to merge 29 commits into
musescore:mainfrom
ToranadoMusic:score-to-video

Conversation

@ToranadoMusic

@ToranadoMusic ToranadoMusic commented May 8, 2026

Copy link
Copy Markdown

#33442

Summary

Adds a native score-to-video workflow to MuseScore Studio. Users can attach one reference video to a score, open a dockable Video panel, keep the video synced to MuseScore playback, control the video audio from the Mixer through a dedicated Video channel, place absolute video hit points, and view SMPTE-style timecode/hit-point information in the Video panel and Timeline.

Motivation

Composers working on film, games, animation, theater, dance, and other picture-locked media often need to write notation against video. Today that workflow usually requires running MuseScore beside a separate video player or DAW, which makes playhead sync, offset handling, save/load, hit-point spotting, and audio control fragile.

Implementation

  • Adds per-score video attachment settings stored in videosettings.json inside the score package.
  • Persists video path, offset in milliseconds, volume, balance, mute, solo, frame rate, timecode display mode, and hit points.
  • Adds a native dockable Video panel using QtMultimedia for video playback.
  • Syncs video play, pause, and seek behavior to MuseScore playback.
  • Handles positive and negative offsets, including the pre-roll case where video waits at 0 instead of looping or jumping.
  • Adds Ctrl+Alt+V to open/toggle the Video panel.
  • Adds a Video channel to the Mixer model, positioned before Metronome.
  • Uses the normal mixer sections for pan/balance, fader, mute, solo, title strip, and alignment.
  • Keeps irrelevant instrument/source controls blank for Video.
  • Applies Video solo behavior in PlaybackController, so it works even when the Mixer panel is not open.
  • Keeps the Video panel layout stable when docked or floating: preview on top, controls underneath.
  • Adds SMPTE-style HH:MM:SS:FF formatting based on the stored video frame rate.
  • Adds Video panel controls for timecode display mode and frame rate.
  • Adds absolute video hit points that are stored as video milliseconds, not score ticks.
  • Resolves each hit point's current musical position from the score tempo map, so tempo edits before the hit point move its displayed bar/beat while the video frame stays fixed.
  • Adds a visual hit-point overlay in the Video panel.
  • Extends the native Timeline with Timecode and Hit points meta rows, alongside existing tempo and time signature rows.
  • Refreshes the Timeline when video settings change.

Validation

  • Windows Debug build: MuseScoreStudio, project_test, playback_qml, and notationscene targets build successfully.
  • Focused tests: project_test and playback_test pass under CTest with the Qt runtime on PATH.
  • git diff --check reports no patch whitespace errors.
  • Project video settings serialization test covers persisted frame rate, timecode display mode, and hit points.

Contributor Checklist

  • I signed the CLA.
  • The title of the PR describes the problem it addresses.
  • Each commit's message describes its purpose and effects. The changes are split into 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. 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 where applicable.

@ToranadoMusic

ToranadoMusic commented May 8, 2026

Copy link
Copy Markdown
Author

Updated the mixer integration for the score-to-video patch.

What changed:

  • Video is now represented as a real MixerChannelItem::Video in MixerPanelModel, inserted before the Metronome channel.
  • Removed the custom hand-built Video strip from MixerPanel.qml, so the existing mixer sections now render Video with the same row heights/alignment as the other channels.
  • Kept Sound/Aux rows visually empty for Video since the media source comes from the attached video rather than an instrument/reverb path.
  • Added persisted video balance so the normal mixer pan/balance control has a model value alongside volume, mute, and solo.
  • Kept the title strip color distinct for Video.

Verification:

  • Debug build and install completed successfully.
  • Launched MuseScoreStudio5Development; process opened and responded.
  • Runtime log check showed no new VideoPanel/MixerPanel QML errors or missing-type errors.

@ToranadoMusic

Copy link
Copy Markdown
Author

Follow-up fix for bottom-docked Video panel clipping:

  • Removed the hard 360px minimum width from the Video controls column.
  • Switched the panel from a fixed horizontal RowLayout to a responsive GridLayout.
  • When the dock gets narrow, the preview and controls stack vertically instead of letting Browse/Clear run off the right edge.
  • Build/install succeeded and the app launched with no new VideoPanel QML runtime errors.

@ToranadoMusic

Copy link
Copy Markdown
Author

Follow-up video panel sizing change:

  • Removed the remaining thumbnail-style cap from the video preview.
  • The preview now fills the available panel width and height, with the controls taking only their implicit space.
  • In compact/bottom-docked layouts, the video area grows as the dock or floating panel gets taller instead of staying at a fixed 96px height.

Verification:

  • Debug build/install succeeded.
  • Launched MuseScoreStudio5Development; process opened and responded.
  • Runtime log check showed no new VideoPanel QML errors or binding-loop warnings.

@ToranadoMusic

Copy link
Copy Markdown
Author

Fixed two playback behavior bugs from testing:

  • Video solo now mutes MuseScore's master playback path at runtime, so soloing the Video channel leaves the video audio audible while silencing score playback. Disabling Video solo restores the master control state from project audio settings.
  • Negative video offsets no longer clamp-and-play at video time 0. If scorePlaybackPositionMs + offsetMs is still negative, the video seeks/stays at 0 and pauses until the score catches up to the video start.

Verification:

  • Debug build/install succeeded.
  • Launched MuseScoreStudio5Development; process opened and responded.
  • Runtime log check showed no new VideoPanel/MixerPanel QML errors or binding-loop warnings.

@ToranadoMusic

Copy link
Copy Markdown
Author

Video panel layout follow-up:

  • Kept the Video panel in a stable vertical layout: preview on top, transport/file/offset/clear controls underneath.
  • Removed the width-based switch back to the side-by-side layout so floating/undocked panels keep the same layout as the tested compact view.
  • The preview still expands into the available remaining space above the controls.

Verification:

  • Debug build/install succeeded.
  • Launched MuseScoreStudio5Development; process opened and responded.
  • Runtime log check showed no new VideoPanel QML errors or binding-loop warnings.

@ToranadoMusic ToranadoMusic changed the title Add native video sync proposal Add native score-to-video sync May 8, 2026
@ToranadoMusic

ToranadoMusic commented May 8, 2026

Copy link
Copy Markdown
Author

PR readiness update: refreshed the description to reflect the current implementation, scope, known limitations, and a concrete tester checklist. Also moved Video solo behavior into PlaybackController so it is no longer dependent on the Mixer UI being open.

@igorkorsukov
igorkorsukov changed the base branch from master to main May 14, 2026 14:14
@ToranadoMusic

Copy link
Copy Markdown
Author

Less formal comment this time.

CLA Has Now Been signed, however, working out a few more bugs with exporting video alongside the new Video Export feature in 4.7. Also attempting to make it more compatible with the system we are now semi-required to download alongside of Musescore in order to do video export and having it decode the video to better implement the audio into the normal audio workflow.

@cbjeukendrup

Copy link
Copy Markdown
Collaborator

It looks like this PR needs a rebase (git pull --rebase upstream main; git push -f); there are currently some commits that are not expected to be listed here.

@ToranadoMusic
ToranadoMusic marked this pull request as ready for review May 26, 2026 17:14
@coderabbitai

coderabbitai Bot commented May 26, 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
📝 Walkthrough

Walkthrough

This pull request implements project-level video attachment support: new types and IProjectVideoSettings, ProjectVideoSettings persistence with MSC read/write, NotationProject wiring, playback controller integration for master mute/solo, mixer Video channel and controls, a VideoPanel QML UI and VideoPanelModel bridge, timeline timecode/hit-point meta rows, appshell actions/shortcuts, build updates for Qt Multimedia, and unit tests for settings persistence.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.25% 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 'Add native score-to-video sync' clearly and concisely describes the main feature addition - native video synchronization functionality for scores.
Description check ✅ Passed The PR description is comprehensive, covering motivation, implementation details, validation, and a completed contributor checklist. All required template sections are filled with relevant information.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Linked repositories: Your configuration references 1 linked repositories, but your current plan allows 0. 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: 5

🤖 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/CMakeLists.txt`:
- Line 21: The unconditional find_package(Qt6 REQUIRED COMPONENTS Multimedia)
should be guarded by the playback build option; wrap the find_package call so it
only runs when MUE_BUILD_PLAYBACK_MODULE is enabled (the same option that
controls the consumer target_link_libraries(... Qt6::Multimedia) in the playback
QML CMake). Modify src/CMakeLists.txt to check MUE_BUILD_PLAYBACK_MODULE before
calling find_package(Qt6 COMPONENTS Multimedia) (or make the component optional)
so non-playback builds do not require Qt6::Multimedia during configuration.

In `@src/engraving/infrastructure/mscreader.cpp`:
- Around line 246-249: readVideoSettingsJsonFile currently calls
fileData("videosettings.json") unconditionally which triggers error paths/log
spam when the file is absent; modify MscReader::readVideoSettingsJsonFile to
first check fileExists(u"videosettings.json") and only call fileData(...) when
present, otherwise return an empty ByteArray (or appropriate default) so no
false errors are logged by the reader. Ensure you use the existing
MscReader::fileExists and MscReader::fileData helpers to locate the change.

In `@src/playback/qml/MuseScore/Playback/mixerpanelmodel.cpp`:
- Around line 52-55: videoVolumeFromDb currently converts dB to linear with
muse::db_to_linear(volume).raw() which can return a tiny non-zero value for the
dB value that represents exact silence (-60 dB produced by videoVolumeToDb(0)),
causing saved volume=0 to be bumped; fix by special-casing that sentinel dB
value: if volume equals the dB value produced by videoVolumeToDb(0) (or the
constant -60 dB if used), return 0.f immediately, otherwise continue to return
std::clamp(muse::db_to_linear(volume).raw(), 0.f, 1.f); update videoVolumeFromDb
to reference videoVolumeToDb/video silent-constant and muse::db_to_linear so the
intent is clear.

In `@src/playback/qml/MuseScore/Playback/VideoPanel.qml`:
- Around line 277-282: The onTextEditingFinished handler uses
parseInt(newTextValue) without a radix; change the call in the
onTextEditingFinished function to parseInt(newTextValue, 10) to ensure decimal
parsing and then assign videoModel.offsetMs as before (preserving the existing
isNaN check).

In `@src/project/internal/projectvideosettings.cpp`:
- Around line 68-70: ProjectVideoSettings::read currently calls
QJsonDocument::fromJson(...).object() without error checking and ignores the
persisted VIDEO_SETTINGS_VERSION; update read to parse with a QJsonParseError,
verify error.error == QJsonParseError::NoError before using the document, then
validate the root JSON contains a "version" that matches VIDEO_SETTINGS_VERSION
(or handle known migration paths) and that "attachment" exists and is an object;
only after those checks assign m_attachment =
attachmentFromJson(rootObj.value("attachment").toObject()); reference
QJsonDocument::fromJson, QJsonParseError, VIDEO_SETTINGS_VERSION,
ProjectVideoSettings::read, m_attachment, and attachmentFromJson when locating
the code to change.
🪄 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: 1596b7e7-1c75-4443-a12c-9532680a41ae

📥 Commits

Reviewing files that changed from the base of the PR and between 664fe3f and 5b18a83.

📒 Files selected for processing (35)
  • src/CMakeLists.txt
  • src/app/configs/data/shortcuts.xml
  • src/app/configs/data/shortcuts_azerty.xml
  • src/app/configs/data/shortcuts_mac.xml
  • src/appshell/appshelltypes.h
  • src/appshell/internal/applicationuiactions.cpp
  • src/appshell/qml/MuseScore/AppShell/NotationPage/NotationPage.qml
  • src/appshell/qml/MuseScore/AppShell/appmenumodel.cpp
  • src/appshell/qml/MuseScore/AppShell/notationpagemodel.cpp
  • src/appshell/qml/MuseScore/AppShell/notationpagemodel.h
  • src/engraving/infrastructure/mscreader.cpp
  • src/engraving/infrastructure/mscreader.h
  • src/engraving/infrastructure/mscwriter.cpp
  • src/engraving/infrastructure/mscwriter.h
  • src/playback/internal/playbackcontroller.cpp
  • src/playback/internal/playbackcontroller.h
  • src/playback/qml/MuseScore/Playback/CMakeLists.txt
  • src/playback/qml/MuseScore/Playback/MixerPanel.qml
  • src/playback/qml/MuseScore/Playback/VideoPanel.qml
  • src/playback/qml/MuseScore/Playback/internal/MixerAuxSendsSection.qml
  • src/playback/qml/MuseScore/Playback/internal/MixerTitleSection.qml
  • src/playback/qml/MuseScore/Playback/mixerchannelitem.h
  • src/playback/qml/MuseScore/Playback/mixerpanelmodel.cpp
  • src/playback/qml/MuseScore/Playback/mixerpanelmodel.h
  • src/playback/qml/MuseScore/Playback/videopanelmodel.cpp
  • src/playback/qml/MuseScore/Playback/videopanelmodel.h
  • src/project/CMakeLists.txt
  • src/project/inotationproject.h
  • src/project/internal/notationproject.cpp
  • src/project/internal/notationproject.h
  • src/project/internal/projectvideosettings.cpp
  • src/project/internal/projectvideosettings.h
  • src/project/iprojectvideosettings.h
  • src/project/tests/CMakeLists.txt
  • src/project/tests/projectvideosettingstest.cpp

Comment thread src/CMakeLists.txt Outdated
Comment thread src/engraving/infrastructure/mscreader.cpp
Comment thread src/playback/qml/MuseScore/Playback/mixerpanelmodel.cpp
Comment thread src/playback/qml/MuseScore/Playback/VideoPanel.qml
Comment thread src/project/internal/projectvideosettings.cpp Outdated
@shoogle

shoogle commented May 27, 2026

Copy link
Copy Markdown
Contributor

@ToranadoMusic, what's your username on MuseScore.org for the account you used to sign the CLA?

If you're not sure, you can find out your username at https://musescore.org/en/user.

@ToranadoMusic

Copy link
Copy Markdown
Author

@shoogle I have signed the CLA with the account toranmorton
image

@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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/project/internal/projectvideosettings.cpp (1)

45-52: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Normalize hitPoints in setAttachment().

attachmentFromJson() sorts hitPoints, but Line 51 stores caller order verbatim. Timeline::hitPointMeta() then iterates attachment.hitPoints directly in src/notationscene/widgets/timeline.cpp:1493-1518, so newly added/edited hit points can render in the wrong order until the score is saved and reopened. Canonicalize before the equality check so live behavior matches the persisted model.

Proposed fix
 void ProjectVideoSettings::setAttachment(const VideoAttachmentSettings& attachment)
 {
-    if (m_attachment == attachment) {
+    VideoAttachmentSettings normalized = attachment;
+    std::stable_sort(normalized.hitPoints.begin(), normalized.hitPoints.end(),
+                     [](const VideoHitPointSettings& a, const VideoHitPointSettings& b) {
+        return a.timeMs < b.timeMs;
+    });
+
+    if (m_attachment == normalized) {
         return;
     }
 
-    m_attachment = attachment;
+    m_attachment = std::move(normalized);
     m_settingsChanged.notify();
 }
🤖 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/project/internal/projectvideosettings.cpp` around lines 45 - 52, The
setAttachment problem is that it stores attachment.hitPoints in caller order so
live rendering differs from the persisted, sorted model; update
ProjectVideoSettings::setAttachment to canonicalize (sort) attachment.hitPoints
the same way attachmentFromJson does (use the same comparator or shared helper
used elsewhere) before comparing to m_attachment and before assigning
m_attachment and calling m_settingsChanged.notify(); ensure you normalize
hitPoints so Timeline::hitPointMeta which iterates attachment.hitPoints sees the
same order as the persisted model.
🤖 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/notationscene/widgets/timeline.cpp`:
- Around line 1544-1545: The long initializer for videoPositionMs violates
uncrustify formatting; refactor the expression in timeline.cpp by breaking the
computation into clearly indented subexpressions or intermediate variables
(e.g., compute ticks = seg->measure()->tick().ticks(), timeSec =
score()->utick2utime(ticks), timeMs = std::lround(timeSec * 1000.0) and then use
std::max(0, static_cast<int>(timeMs) + attachment.offsetMs)) so the line wraps
conform to the repo codestyle while preserving the same semantics for
videoPositionMs.
- Line 1517: The synthetic video-metadata rows are being given a segment pointer
(seg) when calling addMetaValue, which incorrectly routes clicks into the
segment-selection branch in Timeline::mousePressEvent; update the addMetaValue
calls for these synthetic rows (the calls around the occurrences using the local
variable seg at the shown sites) to pass nullptr for the segment parameter
(instead of seg) so clicks target only the measure metadata rather than
selecting the measure's first segment.
- Around line 1507-1510: The code currently clamps negative score-relative times
to zero so pre-roll hit points get mapped to measure 1; instead detect the raw
delta (hitPoint.timeMs - attachment.offsetMs) and if it's negative skip/continue
before computing scoreTimeSeconds and tick. Update the logic around
scoreTimeSeconds/tick/measure (references: hitPoint.timeMs, attachment.offsetMs,
scoreTimeSeconds, tick, score()->utime2utick, score()->tick2measure, measure,
currentMeasureIndex) to early-return or continue when the hit point occurs
before the score start rather than clamping to zero.

In `@src/playback/qml/MuseScore/Playback/videopanelmodel.cpp`:
- Around line 100-118: In VideoPanelModel::formatTimecode the code computes
totalFrames using the fractional framesPerSecond but then splits frames/seconds
using roundedFrameRate, causing drift for non-integer FPS (e.g., 29.97). Fix by
computing totalFrames with the same integer rate: compute roundedFrameRate first
(as you already do) and replace the totalFrames calculation to use
roundedFrameRate (e.g. totalFrames = floor((videoPositionMs / 1000.0) *
roundedFrameRate + 0.5)) so seconds and frames remain aligned; keep the rest of
the decomposition (frames, totalSeconds, seconds, minutes, hours) unchanged.

---

Outside diff comments:
In `@src/project/internal/projectvideosettings.cpp`:
- Around line 45-52: The setAttachment problem is that it stores
attachment.hitPoints in caller order so live rendering differs from the
persisted, sorted model; update ProjectVideoSettings::setAttachment to
canonicalize (sort) attachment.hitPoints the same way attachmentFromJson does
(use the same comparator or shared helper used elsewhere) before comparing to
m_attachment and before assigning m_attachment and calling
m_settingsChanged.notify(); ensure you normalize hitPoints so
Timeline::hitPointMeta which iterates attachment.hitPoints sees the same order
as the persisted model.
🪄 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: c06d651d-e7fc-40b1-9637-02da9584e74f

📥 Commits

Reviewing files that changed from the base of the PR and between b595e28 and b77a7f4.

📒 Files selected for processing (10)
  • src/notationscene/qml/MuseScore/NotationScene/timelineview.cpp
  • src/notationscene/widgets/timeline.cpp
  • src/notationscene/widgets/timeline.h
  • src/playback/qml/MuseScore/Playback/VideoPanel.qml
  • src/playback/qml/MuseScore/Playback/videopanelmodel.cpp
  • src/playback/qml/MuseScore/Playback/videopanelmodel.h
  • src/project/internal/projectvideosettings.cpp
  • src/project/internal/projectvideosettings.h
  • src/project/iprojectvideosettings.h
  • src/project/tests/projectvideosettingstest.cpp
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/project/internal/projectvideosettings.h
  • src/project/tests/projectvideosettingstest.cpp

Comment thread src/notationscene/widgets/timeline.cpp Outdated
Comment thread src/notationscene/widgets/timeline.cpp Outdated
Comment thread src/notationscene/widgets/timeline.cpp Outdated
Comment thread src/playback/qml/MuseScore/Playback/videopanelmodel.cpp
@ToranadoMusic
ToranadoMusic marked this pull request as draft June 4, 2026 00:13
@ToranadoMusic
ToranadoMusic marked this pull request as ready for review June 5, 2026 16:31

@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: 1

🤖 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/engraving/style/textstyle.cpp`:
- Around line 1830-1832: allTextStyles() currently skips
TextStyleType::VIDEO_HIT_POINT but editableTextStyles() later reinserts
VIDEO_HIT_POINT after TextStyleType::SYSTEM and removes DYNAMICS; clarify intent
by either aligning the rules or documenting why VIDEO_HIT_POINT is excluded
globally but reintroduced for the editor: add a short comment in allTextStyles()
explaining why VIDEO_HIT_POINT is omitted (e.g., it is editor-only / rendered
differently at runtime), and mirror that rationale as a comment in
editableTextStyles() where VIDEO_HIT_POINT is inserted (and note the DYNAMICS
removal), or if the omission was accidental, change allTextStyles() to include
VIDEO_HIT_POINT so both functions are consistent.
🪄 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: cdb4aef7-94e8-4c0d-9e90-ccefda6a413f

📥 Commits

Reviewing files that changed from the base of the PR and between b77a7f4 and ea80d69.

📒 Files selected for processing (25)
  • src/CMakeLists.txt
  • src/appshell/internal/applicationuiactions.cpp
  • src/appshell/internal/applicationuiactions.h
  • src/appshell/qml/MuseScore/AppShell/NotationPage/NotationPage.qml
  • src/appshell/qml/MuseScore/AppShell/appmenumodel.cpp
  • src/appshell/qml/MuseScore/AppShell/appmenumodel.h
  • src/appshell/qml/MuseScore/AppShell/notationpagemodel.cpp
  • src/appshell/qml/MuseScore/AppShell/notationpagemodel.h
  • src/engraving/style/styledef.cpp
  • src/engraving/style/styledef.h
  • src/engraving/style/textstyle.cpp
  • src/engraving/types/types.h
  • src/engraving/types/typesconv.cpp
  • src/notationscene/qml/MuseScore/NotationScene/abstractnotationpaintview.cpp
  • src/notationscene/qml/MuseScore/NotationScene/abstractnotationpaintview.h
  • src/notationscene/widgets/editstyle.cpp
  • src/notationscene/widgets/editstyle.h
  • src/notationscene/widgets/editstyleutils.cpp
  • src/notationscene/widgets/timeline.cpp
  • src/playback/qml/MuseScore/Playback/CMakeLists.txt
  • src/playback/qml/MuseScore/Playback/VideoPanel.qml
  • src/playback/qml/MuseScore/Playback/mixerpanelmodel.cpp
  • src/playback/qml/MuseScore/Playback/videopanelmodel.cpp
  • src/playback/qml/MuseScore/Playback/videopanelmodel.h
  • src/project/internal/projectvideosettings.cpp
✅ Files skipped from review due to trivial changes (2)
  • src/engraving/types/types.h
  • src/notationscene/qml/MuseScore/NotationScene/abstractnotationpaintview.h
🚧 Files skipped from review as they are similar to previous changes (7)
  • src/CMakeLists.txt
  • src/appshell/qml/MuseScore/AppShell/NotationPage/NotationPage.qml
  • src/playback/qml/MuseScore/Playback/videopanelmodel.h
  • src/playback/qml/MuseScore/Playback/CMakeLists.txt
  • src/playback/qml/MuseScore/Playback/mixerpanelmodel.cpp
  • src/project/internal/projectvideosettings.cpp
  • src/notationscene/widgets/timeline.cpp

Comment thread src/engraving/style/textstyle.cpp

@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.

🧹 Nitpick comments (1)
src/engraving/style/textstyle.cpp (1)

1857-1864: 💤 Low value

Consider adding a defensive check for SYSTEM not found.

While SYSTEM should always be present in _editableTextStyles, adding a defensive check would make the code more robust against future changes.

🛡️ Optional defensive code
+    bool found = false;
     for (auto it = _editableTextStyles.begin(); it != _editableTextStyles.end(); ++it) {
         if (*it == TextStyleType::SYSTEM) {
             _editableTextStyles.insert(++it, TextStyleType::VIDEO_HIT_POINT);
+            found = true;
             break;
         }
     }
+    if (!found) {
+        LOGE() << "SYSTEM text style not found in editableTextStyles; VIDEO_HIT_POINT not inserted";
+    }
🤖 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/engraving/style/textstyle.cpp` around lines 1857 - 1864, The loop that
reinserts TextStyleType::VIDEO_HIT_POINT assumes TextStyleType::SYSTEM exists in
_editableTextStyles; add a defensive check so you only call
_editableTextStyles.insert(++it, TextStyleType::VIDEO_HIT_POINT) when SYSTEM was
actually found (e.g., track a found flag or use std::find to locate
TextStyleType::SYSTEM), and avoid advancing/inserting if SYSTEM is not present
to prevent invalid iterator use.
🤖 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.

Nitpick comments:
In `@src/engraving/style/textstyle.cpp`:
- Around line 1857-1864: The loop that reinserts TextStyleType::VIDEO_HIT_POINT
assumes TextStyleType::SYSTEM exists in _editableTextStyles; add a defensive
check so you only call _editableTextStyles.insert(++it,
TextStyleType::VIDEO_HIT_POINT) when SYSTEM was actually found (e.g., track a
found flag or use std::find to locate TextStyleType::SYSTEM), and avoid
advancing/inserting if SYSTEM is not present to prevent invalid iterator use.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ff2429f7-7fcf-4615-9c2c-c9790fab919c

📥 Commits

Reviewing files that changed from the base of the PR and between ea80d69 and 08a0bc4.

📒 Files selected for processing (1)
  • src/engraving/style/textstyle.cpp

@cfirwin3

Copy link
Copy Markdown

Linux build:
MU4_260612173_Lin_x86_64_33323

Hangs on splash screen.

Ubuntu 26.04

@ToranadoMusic

Copy link
Copy Markdown
Author

Linux build: MU4_260612173_Lin_x86_64_33323

Hangs on splash screen.

Ubuntu 26.04

Check the new build to see if it fixed it

@cfirwin3

Copy link
Copy Markdown

Linux build: MU4_260612173_Lin_x86_64_33323
Hangs on splash screen.
Ubuntu 26.04

Check the new build to see if it fixed it

New build opens. Video panel is blank and lacks any controls or interface to load/display video.
Still Ubuntu 26.04

Operation of any video capability is unclear.

@ToranadoMusic

Copy link
Copy Markdown
Author

Linux build: MU4_260612173_Lin_x86_64_33323
Hangs on splash screen.
Ubuntu 26.04

Check the new build to see if it fixed it

New build opens. Video panel is blank and lacks any controls or interface to load/display video. Still Ubuntu 26.04

Operation of any video capability is unclear.

Ok, I tried something, let me know how it goes, I'll be gone for a week, so i won't be able to make any updates until after that, but I will make any changes needed whenever I get back.
image
It Should look something like this

@cfirwin3

Copy link
Copy Markdown

Linux build: MU4_260612173_Lin_x86_64_33323
Hangs on splash screen.
Ubuntu 26.04

Check the new build to see if it fixed it

New build opens. Video panel is blank and lacks any controls or interface to load/display video. Still Ubuntu 26.04
Operation of any video capability is unclear.

Ok, I tried something, let me know how it goes, I'll be gone for a week, so i won't be able to make any updates until after that, but I will make any changes needed whenever I get back. image It Should look something like this

It looks to be the same as before. I am assuming that there should be a viewer, controls, and a folder browser to load a video. But it comes up as a blank tab, as before. Does this PR access Qtmultimedia from the distro or is it containerized in the appimage?

No worries on the time table. I'm just happy to help test and troubleshoot for Linux or general use so long as you need it.

@diedeno

diedeno commented Jun 27, 2026

Copy link
Copy Markdown
Contributor

Ubuntu 24.04:
10:28:23.414 | WARN | main_thread | Qt | qrc:/qt/qml/MuseScore/Playback/VideoPanel.qml:28:1: module "QtMultimedia" is not installed
See #27568 for an earlier videoplayer build.
QtMultimedia must be in the Appimage for this to work on Linux.

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.

7 participants