Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
a48ff15
Add per-note playback start/duration offset properties
tharosd Aug 11, 2026
756caf5
Fix note playback offset copy and add duration safety clamps
tharos-devs Aug 13, 2026
8990603
Add drag-handle overlay to edit per-note playback start/duration offsets
tharos-devs Aug 13, 2026
b84570b
Rebuild note-offset overlay geometry on style changes
tharos-devs Aug 13, 2026
009a628
Fix repeat/volta playback timing and start/duration clamp mismatch
tharos-devs Aug 14, 2026
d14be1b
Merge branch 'feature/note-offsets' into feature/note-offset-drag-han…
tharos-devs Aug 14, 2026
b74429c
Fix crash and lifecycle bugs in the note-offset drag-handle overlay
tharos-devs Aug 14, 2026
b0d68ec
Add drag-handle overlay to edit per-note velocities
tharos-devs Aug 14, 2026
2e1c2ad
Bump muse_framework submodule for note velocity override forwarding
tharos-devs Aug 14, 2026
ae924b1
Merge remote-tracking branch 'origin/main' into feature/note-offsets
tharos-devs Aug 14, 2026
5fc3d1a
Merge branch 'feature/note-offsets' into feature/note-offset-drag-han…
tharos-devs Aug 14, 2026
9702adc
Merge branch 'feature/note-offset-drag-handles' into feature/note-vel…
tharos-devs Aug 14, 2026
52bd183
Fix codestyle (uncrustify) violation in NotationNoteOffsetController
tharos-devs Aug 14, 2026
be48c0d
Point muse submodule back at upstream main
tharos-devs Aug 14, 2026
fdd2101
Merge branch 'feature/note-offsets' into feature/note-offset-drag-han…
tharos-devs Aug 14, 2026
ee2b643
Merge branch 'feature/note-offset-drag-handles' into feature/note-vel…
tharos-devs Aug 14, 2026
c4a8b0d
Re-pin muse submodule to velocity fix, fix codestyle violation
tharos-devs Aug 14, 2026
12ad719
Fix playback timing regression for grace notes, arpeggios and bends
tharos-devs Aug 14, 2026
b2c9257
Merge branch 'feature/note-offsets' into feature/note-offset-drag-han…
tharos-devs Aug 14, 2026
716b2e1
Merge branch 'feature/note-offset-drag-handles' into feature/note-vel…
tharos-devs Aug 14, 2026
59e5ccc
Fix codestyle (uncrustify) violation in NoteRenderer::render()
tharos-devs Aug 14, 2026
7e4762d
Merge branch 'feature/note-offsets' into feature/note-offset-drag-han…
tharos-devs Aug 14, 2026
8516f5d
Merge branch 'feature/note-offset-drag-handles' into feature/note-vel…
tharos-devs Aug 14, 2026
917b4f9
Show a live numeric readout next to the bar while dragging a velocity…
tharos-devs Aug 14, 2026
dd03a90
Fix playback start/duration offset not surviving save/reload
tharos-devs Aug 14, 2026
1100bcf
Merge branch 'feature/note-offsets' into feature/note-offset-drag-han…
tharos-devs Aug 14, 2026
fb8b0e4
Merge branch 'feature/note-offset-drag-handles' into feature/note-vel…
tharos-devs Aug 14, 2026
142dde7
Fix note-offset rectangle width when another voice has a shorter note
tharos-devs Aug 14, 2026
e0d7ad5
Merge branch 'feature/note-offset-drag-handles' into feature/note-vel…
tharos-devs Aug 14, 2026
ddfdd63
Fix note velocity not propagating to tied-continuation notes
tharos-devs Aug 15, 2026
2f81c01
Write Pid::VELO_TYPE when saving notes
tharos-devs Aug 15, 2026
8816db7
Color-code note-offset rectangles by modification/selection state
tharos-devs Aug 15, 2026
6116b58
Merge branch 'feature/note-offset-drag-handles' into feature/note-vel…
tharos-devs Aug 15, 2026
76ac7a2
Add "Reset note offsets" context-menu item
tharos-devs Aug 15, 2026
b2ba57a
Merge branch 'feature/note-offset-drag-handles' into feature/note-vel…
tharos-devs Aug 15, 2026
b84d071
Add "Reset note velocities" context-menu item
tharos-devs Aug 15, 2026
558094d
Keep a selected chord note's velocity bar on top and draggable
tharos-devs Aug 15, 2026
4dc153a
Tint note-offset drag handles by the rectangle's own state color
tharos-devs Aug 15, 2026
4e7e8be
Merge branch 'feature/note-offset-drag-handles' into feature/note-vel…
tharos-devs Aug 15, 2026
5efb9d5
Extend note-offset overlay rectangles across full tie chains
tharos-devs Aug 18, 2026
71efc99
Make note-offset Properties panel spinboxes tie-aware
tharos-devs Aug 18, 2026
5a0959e
Merge branch 'feature/note-offset-drag-handles' into feature/note-vel…
tharos-devs Aug 18, 2026
0cda5e4
Show the actual dynamics-derived velocity in the Properties panel
tharos-devs Aug 18, 2026
70acf5b
Give velocity bars cursor priority over note-offset handles they cover
tharos-devs Aug 18, 2026
a147385
Make velocity bar dragging relative instead of jump-to-click
tharos-devs Aug 18, 2026
a07a3cc
Fix velocity-drag delta scale mismatch and redundant cursor updates
tharos-devs Aug 19, 2026
60d054f
Square off note-offset rectangle corners
tharos-devs Aug 19, 2026
bec6daa
Audition the note at its live velocity while dragging its bar
tharos-devs Aug 19, 2026
ee103eb
Add a Cmd/Ctrl-tap toggle to swap note-offset/velocity overlay priority
tharos-devs Aug 19, 2026
a607d10
Click a velocity bar to jump it directly to the clicked position
tharos-devs Aug 19, 2026
5dee821
Fix velocity-drag edge cases: phantom 0->1 bump, incomplete cancel re…
tharos-devs Aug 19, 2026
f378cb0
Force a cursor refresh right after the overlay-priority Cmd/Ctrl tap
tharos-devs Aug 19, 2026
cdba406
Make the Properties panel velocity field VeloType::OFFSET_VAL-aware
tharos-devs Aug 19, 2026
af27a3b
Merge remote-tracking branch 'origin/main' into feature/note-offsets
tharos-devs Aug 19, 2026
69b9700
Merge branch 'feature/note-offsets' into feature/note-offset-drag-han…
tharos-devs Aug 19, 2026
fe707db
Merge branch 'feature/note-offset-drag-handles' into feature/note-vel…
tharos-devs Aug 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/engraving/api/v1/elements.h
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,11 @@ class Note : public EngravingItem
/// The tuning of this note, in cents.
API_PROPERTY_T(qreal, tuning, TUNING)

/// The start time offset for playback, in ticks.
API_PROPERTY_T(int, playbackStartOffset, PLAYBACK_START_OFFSET)
/// The duration offset for playback, in ticks.
API_PROPERTY_T(int, playbackDurationOffset, PLAYBACK_DURATION_OFFSET)

/// For notes on non-tab staves: the line this note is on.
API_PROPERTY_T(int, line, LINE)
/// For notes on non-tab staves: Whether this note is
Expand Down
16 changes: 16 additions & 0 deletions src/engraving/dom/note.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,8 @@ Note::Note(const Note& n, bool link)
m_harmonic = n.m_harmonic;
m_hasParens = n.m_hasParens;
m_hideGeneratedParens = n.m_hideGeneratedParens;
m_playbackStartOffset = n.m_playbackStartOffset;
m_playbackDurationOffset = n.m_playbackDurationOffset;

if (n.m_accidental) {
add(new Accidental(*(n.m_accidental)));
Expand Down Expand Up @@ -3134,6 +3136,10 @@ PropertyValue Note::getProperty(Pid propertyId) const
return fixed();
case Pid::FIXED_LINE:
return fixedLine();
case Pid::PLAYBACK_START_OFFSET:
return m_playbackStartOffset;
case Pid::PLAYBACK_DURATION_OFFSET:
return m_playbackDurationOffset;
case Pid::HAS_PARENTHESES:
return m_hasParens ? ParenthesesMode::BOTH : ParenthesesMode::NONE;
case Pid::HIDE_GENERATED_PARENTHESES:
Expand Down Expand Up @@ -3242,6 +3248,12 @@ bool Note::setProperty(Pid propertyId, const PropertyValue& v)
case Pid::FIXED_LINE:
setFixedLine(v.toInt());
break;
case Pid::PLAYBACK_START_OFFSET:
setPlaybackStartOffset(v.toInt());
break;
case Pid::PLAYBACK_DURATION_OFFSET:
setPlaybackDurationOffset(v.toInt());
break;
case Pid::HAS_PARENTHESES:
if (v.value<ParenthesesMode>() != ParenthesesMode::BOTH && v.value<ParenthesesMode>() != ParenthesesMode::NONE) {
ASSERT_X("Notes cannot set left & right parens individually");
Expand Down Expand Up @@ -3308,6 +3320,10 @@ PropertyValue Note::propertyDefault(Pid propertyId) const
return 0;
case Pid::TPC2:
return getProperty(Pid::TPC1);
case Pid::PLAYBACK_START_OFFSET:
return 0;
case Pid::PLAYBACK_DURATION_OFFSET:
return 0;
case Pid::PITCH:
case Pid::TPC1:
return PropertyValue();
Expand Down
9 changes: 9 additions & 0 deletions src/engraving/dom/note.h
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,12 @@ class Note final : public EngravingItem
bool isTrillCueNote() const { return m_isTrillCueNote; }
void setIsTrillCueNote(bool v);

int playbackStartOffset() const { return m_playbackStartOffset; }
void setPlaybackStartOffset(int offset) { m_playbackStartOffset = offset; }

int playbackDurationOffset() const { return m_playbackDurationOffset; }
void setPlaybackDurationOffset(int offset) { m_playbackDurationOffset = offset; }

SymId noteHead() const;
bool isNoteName() const;

Expand Down Expand Up @@ -561,5 +567,8 @@ class Note final : public EngravingItem

std::vector<LineAttachPoint> m_lineAttachPoints;
TieJumpPointList m_jumpPoints { this };

int m_playbackStartOffset = 0; // offset in ticks to add to chord's tick for playback start
int m_playbackDurationOffset = 0; // offset in ticks to add to chord's ticks for playback duration
};
} // namespace mu::engraving
3 changes: 3 additions & 0 deletions src/engraving/dom/property.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -519,6 +519,9 @@ static constexpr PropertyMetaData propertyList[] = {

{ Pid::SHARED_PART_ENABLED, P_TYPE::BOOL, PropertyGroup::NONE, false, "sharedPartEnabled", QT_TRANSLATE_NOOP("engraving/propertyName", "shared part enabled") },

{ Pid::PLAYBACK_START_OFFSET, P_TYPE::INT, PropertyGroup::APPEARANCE, false, "playbackStartOffset", QT_TRANSLATE_NOOP("engraving/propertyName", "playback start offset") },
{ Pid::PLAYBACK_DURATION_OFFSET, P_TYPE::INT, PropertyGroup::APPEARANCE, false, "playbackDurationOffset", QT_TRANSLATE_NOOP("engraving/propertyName", "playback duration offset") },

{ Pid::END, P_TYPE::INT, PropertyGroup::NONE, false, "++end++", nullptr }
};
/* *INDENT-ON* */
Expand Down
3 changes: 3 additions & 0 deletions src/engraving/dom/property.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,9 @@ enum class Pid : short {

SHARED_PART_ENABLED,

PLAYBACK_START_OFFSET,
PLAYBACK_DURATION_OFFSET,

END
};

Expand Down
10 changes: 10 additions & 0 deletions src/engraving/playback/playbackmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,16 @@ muse::async::Channel<InstrumentTrackId> PlaybackModel::trackRemoved() const
return m_trackRemoved;
}

dynamic_level_t PlaybackModel::appliableDynamicLevel(track_idx_t trackIdx, int tick) const
{
if (!m_playbackCtx) {
return dynamicLevelFromType(muse::mpe::DynamicType::Natural);
}

const int utick = repeatList().tick2utick(tick);
return m_playbackCtx->appliableDynamicLevel(trackIdx, utick);
}

void PlaybackModel::update(const int tickFrom, const int tickTo, const track_idx_t trackFrom, const track_idx_t trackTo,
ChangedTrackIdSet* trackChanges)
{
Expand Down
2 changes: 2 additions & 0 deletions src/engraving/playback/playbackmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class PlaybackModel : public muse::Contextable, public muse::async::Asyncable
muse::async::Channel<InstrumentTrackId> trackAdded() const;
muse::async::Channel<InstrumentTrackId> trackRemoved() const;

muse::mpe::dynamic_level_t appliableDynamicLevel(track_idx_t trackIdx, int tick) const;

private:
static const InstrumentTrackId METRONOME_TRACK_ID;
static const InstrumentTrackId CHORD_SYMBOLS_TRACK_ID;
Expand Down
20 changes: 20 additions & 0 deletions src/engraving/playback/renderers/noterenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,26 @@ void NoteRenderer::render(const Note* note, const RenderingContext& ctx, mpe::Pl
return;
}

if (note->playbackStartOffset() != 0 || note->playbackDurationOffset() != 0) {
// playbackStartOffset()/playbackDurationOffset() are ticks relative to the note's own
// nominal position - apply them on top of ctx's nominal tick range rather than
// recomputing from the chord's own tick()/ticks(). The chord's tick()/ticks() are its
// notated position/duration, which for a grace note or a note inside a repeated section
// is NOT the same as when/how long it actually plays - ctx.nominalPositionStartTick/
// nominalPositionEndTick already reflect that (see GraceChordCtx::buildCtx), whereas
// chord->tick() would collapse a grace note's "before the beat" timing back to the
// principal note's tick.
const int nominalStartTick = ctx.nominalPositionStartTick;
const int nominalEndTick = ctx.nominalPositionEndTick + note->playbackDurationOffset();
const int effectiveStartTick = std::max(0, nominalStartTick + note->playbackStartOffset());
const int effectiveDurationTicks = std::max(1, nominalEndTick - effectiveStartTick);

auto effectiveTnD = timestampAndDurationFromStartAndDurationTicks(ctx.score, effectiveStartTick, effectiveDurationTicks,
ctx.positionTickOffset);
noteCtx.timestamp = effectiveTnD.timestamp;
noteCtx.duration = effectiveTnD.duration;
}

const Tie* tieFor = note->tieFor();
if (tieFor && tieFor->playSpanner()) {
if (tieFor->isPartialTie()) {
Expand Down
2 changes: 2 additions & 0 deletions src/engraving/rw/read500/tread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3470,6 +3470,8 @@ bool TRead::readProperties(Note* n, XmlReader& e, ReadContext& ctx)
} else if (tag == "overrideBendVisibilityRules") {
n->setOverrideBendVisibilityRules(e.readBool());
} else if (TRead::readProperty(n, tag, e, ctx, Pid::HIDE_GENERATED_PARENTHESES)) {
} else if (TRead::readProperty(n, tag, e, ctx, Pid::PLAYBACK_START_OFFSET)) {
} else if (TRead::readProperty(n, tag, e, ctx, Pid::PLAYBACK_DURATION_OFFSET)) {
} else if (readItemProperties(n, e, ctx)) {
} else {
return false;
Expand Down
5 changes: 3 additions & 2 deletions src/engraving/rw/write/twrite.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2505,8 +2505,9 @@ void TWrite::write(const Note* item, XmlWriter& xml, WriteContext& ctx)
xml.endElement();
}
for (Pid id : { Pid::PITCH, Pid::CENT_OFFSET, Pid::TPC1, Pid::TPC2, Pid::SMALL, Pid::MIRROR_HEAD, Pid::DOT_POSITION,
Pid::HEAD_SCHEME, Pid::HEAD_GROUP, Pid::USER_VELOCITY, Pid::PLAY, Pid::TUNING, Pid::FRET, Pid::STRING,
Pid::GHOST, Pid::DEAD, Pid::HEAD_TYPE, Pid::FIXED, Pid::FIXED_LINE }) {
Pid::HEAD_SCHEME, Pid::HEAD_GROUP, Pid::VELO_TYPE, Pid::USER_VELOCITY, Pid::PLAY, Pid::TUNING, Pid::FRET,
Pid::STRING, Pid::GHOST, Pid::DEAD, Pid::HEAD_TYPE, Pid::FIXED, Pid::FIXED_LINE,
Pid::PLAYBACK_START_OFFSET, Pid::PLAYBACK_DURATION_OFFSET }) {
writeProperty(item, xml, id);
}

Expand Down
8 changes: 8 additions & 0 deletions src/engraving/tests/note_tests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,14 @@ TEST_F(Engraving_NoteTests, note)
EXPECT_EQ(n->userVelocity(), 71);
delete n;

// playback start/duration offset
note->setPlaybackStartOffset(120);
note->setPlaybackDurationOffset(-60);
n = toNote(ScoreRW::writeReadElement(note));
EXPECT_EQ(n->playbackStartOffset(), 120);
EXPECT_EQ(n->playbackDurationOffset(), -60);
delete n;

// tuning
note->setTuning(1.3);
n = toNote(ScoreRW::writeReadElement(note));
Expand Down
6 changes: 6 additions & 0 deletions src/notation/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ target_sources(notation PRIVATE
inotationselectionfilter.h
inotationselectionrange.h
inotationautomation.h
inotationnoteoffsets.h
inotationnotevelocity.h
inotationinteraction.h
inotationstyle.h
inotationundostack.h
Expand Down Expand Up @@ -83,6 +85,10 @@ target_sources(notation PRIVATE
internal/notationcontextconfiguration.h
internal/notationautomation.cpp
internal/notationautomation.h
internal/notationnoteoffsets.cpp
internal/notationnoteoffsets.h
internal/notationnotevelocity.cpp
internal/notationnotevelocity.h
internal/notationelements.cpp
internal/notationelements.h
internal/notationinteraction.cpp
Expand Down
2 changes: 2 additions & 0 deletions src/notation/imasternotation.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,8 @@ class IMasterNotation
virtual void initNotationSoloMuteState(const INotationPtr notation) = 0;

virtual INotationAutomationPtr automation() const = 0;
virtual INotationNoteOffsetsPtr noteOffsets() const = 0;
virtual INotationNoteVelocityPtr noteVelocity() const = 0;
};

using IMasterNotationPtr = std::shared_ptr<IMasterNotation>;
Expand Down
6 changes: 6 additions & 0 deletions src/notation/inotation_fwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,4 +84,10 @@ using INotationPlaybackPtr = std::shared_ptr<INotationPlayback>;

class INotationAutomation;
using INotationAutomationPtr = std::shared_ptr<INotationAutomation>;

class INotationNoteOffsets;
using INotationNoteOffsetsPtr = std::shared_ptr<INotationNoteOffsets>;

class INotationNoteVelocity;
using INotationNoteVelocityPtr = std::shared_ptr<INotationNoteVelocity>;
}
39 changes: 39 additions & 0 deletions src/notation/inotationnoteoffsets.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-Studio-CLA-applies
*
* MuseScore Studio
* Music Composition & Notation
*
* Copyright (C) 2026 MuseScore Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once

#include "async/notification.h"

namespace mu::notation {
class INotationNoteOffsets
{
public:
virtual ~INotationNoteOffsets() = default;

virtual bool isEditModeEnabled() const = 0;
virtual void setEditModeEnabled(bool enabled) = 0;
virtual muse::async::Notification editModeEnabledChanged() const = 0;
};

using INotationNoteOffsetsPtr = std::shared_ptr<INotationNoteOffsets>;
}
39 changes: 39 additions & 0 deletions src/notation/inotationnotevelocity.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* SPDX-License-Identifier: GPL-3.0-only
* MuseScore-Studio-CLA-applies
*
* MuseScore Studio
* Music Composition & Notation
*
* Copyright (C) 2026 MuseScore Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

#pragma once

#include "async/notification.h"

namespace mu::notation {
class INotationNoteVelocity
{
public:
virtual ~INotationNoteVelocity() = default;

virtual bool isEditModeEnabled() const = 0;
virtual void setEditModeEnabled(bool enabled) = 0;
virtual muse::async::Notification editModeEnabledChanged() const = 0;
};

using INotationNoteVelocityPtr = std::shared_ptr<INotationNoteVelocity>;
}
4 changes: 4 additions & 0 deletions src/notation/inotationplayback.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,10 @@ class INotationPlayback
virtual muse::async::Channel<engraving::InstrumentTrackId> trackAdded() const = 0;
virtual muse::async::Channel<engraving::InstrumentTrackId> trackRemoved() const = 0;

// Dynamic level (marking/hairpin only, no per-note override) that would apply at this tick,
// for use by UI that needs a musically-coherent baseline (e.g. a velocity editor).
virtual muse::mpe::dynamic_level_t appliableDynamicLevel(engraving::track_idx_t trackIdx, int tick) const = 0;

virtual muse::audio::secs_t totalPlayTime() const = 0;
virtual muse::async::Channel<muse::audio::secs_t> totalPlayTimeChanged() const = 0;

Expand Down
14 changes: 14 additions & 0 deletions src/notation/internal/masternotation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#include "excerptnotation.h"
#include "masternotationparts.h"
#include "notationautomation.h"
#include "notationnoteoffsets.h"
#include "notationnotevelocity.h"
#include "types/scorecreateoptions.h"

#ifdef MUE_BUILD_ENGRAVING_PLAYBACK
Expand Down Expand Up @@ -92,6 +94,8 @@ MasterNotation::MasterNotation(project::INotationProject* project, const muse::m
#endif

m_notationAutomation = std::make_shared<NotationAutomation>(undoStack());
m_notationNoteOffsets = std::make_shared<NotationNoteOffsets>();
m_notationNoteVelocity = std::make_shared<NotationNoteVelocity>();

m_parts->partsChanged().onNotify(this, [this]() {
notifyAboutNotationChanged();
Expand Down Expand Up @@ -766,6 +770,16 @@ INotationAutomationPtr MasterNotation::automation() const
return m_notationAutomation;
}

INotationNoteOffsetsPtr MasterNotation::noteOffsets() const
{
return m_notationNoteOffsets;
}

INotationNoteVelocityPtr MasterNotation::noteVelocity() const
{
return m_notationNoteVelocity;
}

void MasterNotation::initNotationSoloMuteState(const INotationPtr notation)
{
IF_ASSERT_FAILED(notation) {
Expand Down
4 changes: 4 additions & 0 deletions src/notation/internal/masternotation.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ class MasterNotation : public IMasterNotation, public Notation, public std::enab
void initNotationSoloMuteState(const INotationPtr notation) override;

INotationAutomationPtr automation() const override;
INotationNoteOffsetsPtr noteOffsets() const override;
INotationNoteVelocityPtr noteVelocity() const override;

private:
friend class project::NotationProject;
Expand Down Expand Up @@ -102,6 +104,8 @@ class MasterNotation : public IMasterNotation, public Notation, public std::enab
muse::async::Notification m_excerptsChanged;
INotationPlaybackPtr m_notationPlayback = nullptr;
INotationAutomationPtr m_notationAutomation = nullptr;
INotationNoteOffsetsPtr m_notationNoteOffsets = nullptr;
INotationNoteVelocityPtr m_notationNoteVelocity = nullptr;
muse::async::Notification m_hasPartsChanged;

mutable ExcerptNotationList m_potentialExcerpts;
Expand Down
Loading
Loading