diff --git a/src/playback/internal/playbackconfiguration.cpp b/src/playback/internal/playbackconfiguration.cpp index 24402b968f798..84e5b6ea65443 100644 --- a/src/playback/internal/playbackconfiguration.cpp +++ b/src/playback/internal/playbackconfiguration.cpp @@ -129,6 +129,10 @@ void PlaybackConfiguration::init() m_isAuxChannelVisibleChanged.send(idx, val.toBool()); }); } + + settings()->valueChanged(PLAY_NOTES_WHEN_EDITING).onReceive(nullptr, [this](const Val&) { + m_isPlayNotesWhenEditingChanged.notify(); + }); } bool PlaybackConfiguration::playNotesWhenEditing() const @@ -161,6 +165,11 @@ void PlaybackConfiguration::setPlayHarmonyWhenEditing(bool value) settings()->setSharedValue(PLAY_HARMONY_WHEN_EDITING, Val(value)); } +muse::async::Notification PlaybackConfiguration::playNotesWhenEditingChanged() const +{ + return m_isPlayNotesWhenEditingChanged; +} + PlaybackCursorType PlaybackConfiguration::cursorType() const { return settings()->value(PLAYBACK_CURSOR_TYPE_KEY).toEnum(); diff --git a/src/playback/internal/playbackconfiguration.h b/src/playback/internal/playbackconfiguration.h index 8cd8f1670856c..c03404e55fdf2 100644 --- a/src/playback/internal/playbackconfiguration.h +++ b/src/playback/internal/playbackconfiguration.h @@ -47,6 +47,8 @@ class PlaybackConfiguration : public IPlaybackConfiguration, public muse::async: bool playHarmonyWhenEditing() const override; void setPlayHarmonyWhenEditing(bool value) override; + muse::async::Notification playNotesWhenEditingChanged() const override; + PlaybackCursorType cursorType() const override; bool isMixerSectionVisible(MixerSectionType sectionType) const override; @@ -92,6 +94,8 @@ class PlaybackConfiguration : public IPlaybackConfiguration, public muse::async: muse::async::Channel m_isMixerSectionVisibleChanged; muse::async::Channel m_muteHiddenInstrumentsChanged; + + muse::async::Notification m_isPlayNotesWhenEditingChanged; }; } diff --git a/src/playback/internal/playbackcontroller.cpp b/src/playback/internal/playbackcontroller.cpp index daa99f461276c..e133ebdd4df8a 100644 --- a/src/playback/internal/playbackcontroller.cpp +++ b/src/playback/internal/playbackcontroller.cpp @@ -59,6 +59,7 @@ static const ActionCode PAN_CODE("pan"); static const ActionCode REPEAT_CODE("repeat"); static const ActionCode PLAY_CHORD_SYMBOLS_CODE("play-chord-symbols"); static const ActionCode PLAYBACK_SETUP("playback-setup"); +static const ActionCode TOGGLE_HEAR_PLAYBACK_WHEN_EDITING("toggle-hear-playback-when-editing"); static AudioOutputParams makeReverbOutputParams() { @@ -113,6 +114,7 @@ void PlaybackController::init() dispatcher()->reg(this, INPUT_SOUNDING_PITCH, [this]() { PlaybackController::setMidiUseWrittenPitch(false); }); dispatcher()->reg(this, COUNT_IN_CODE, this, &PlaybackController::toggleCountIn); dispatcher()->reg(this, PLAYBACK_SETUP, this, &PlaybackController::openPlaybackSetupDialog); + dispatcher()->reg(this, TOGGLE_HEAR_PLAYBACK_WHEN_EDITING, this, &PlaybackController::toggleHearPlaybackWhenEditing); globalContext()->currentNotationChanged().onNotify(this, [this]() { onNotationChanged(); @@ -140,6 +142,10 @@ void PlaybackController::init() updateLoop(); }); + configuration()->playNotesWhenEditingChanged().onNotify(this, [this]() { + notifyActionCheckedChanged(TOGGLE_HEAR_PLAYBACK_WHEN_EDITING); + }); + m_measureInputLag = configuration()->shouldMeasureInputLag(); } @@ -1436,7 +1442,8 @@ bool PlaybackController::actionChecked(const ActionCode& actionCode) const { PLAY_CHORD_SYMBOLS_CODE, notationConfiguration()->isPlayChordSymbolsEnabled() }, { PAN_CODE, notationConfiguration()->isAutomaticallyPanEnabled() }, { METRONOME_CODE, notationConfiguration()->isMetronomeEnabled() }, - { COUNT_IN_CODE, notationConfiguration()->isCountInEnabled() } + { COUNT_IN_CODE, notationConfiguration()->isCountInEnabled() }, + { TOGGLE_HEAR_PLAYBACK_WHEN_EDITING, configuration()->playNotesWhenEditing() } }; return isChecked[actionCode]; @@ -1631,3 +1638,9 @@ muse::audio::secs_t PlaybackController::playedTickToSecs(int tick) const { return secs_t(notationPlayback()->playedTickToSec(tick)); } + +void PlaybackController::toggleHearPlaybackWhenEditing() +{ + bool wasPlayNotesWhenEditing = configuration()->playNotesWhenEditing(); + configuration()->setPlayNotesWhenEditing(!wasPlayNotesWhenEditing); +} diff --git a/src/playback/internal/playbackcontroller.h b/src/playback/internal/playbackcontroller.h index 78262d878dfbe..8964ed7974990 100644 --- a/src/playback/internal/playbackcontroller.h +++ b/src/playback/internal/playbackcontroller.h @@ -112,6 +112,9 @@ class PlaybackController : public IPlaybackController, public muse::actions::Act void setIsExportingAudio(bool exporting) override; bool canReceiveAction(const muse::actions::ActionCode& code) const override; + + void toggleHearPlaybackWhenEditing() override; + private: muse::audio::IPlayerPtr currentPlayer() const; diff --git a/src/playback/internal/playbackuiactions.cpp b/src/playback/internal/playbackuiactions.cpp index 050f01372ecfc..d7b259c5b67be 100644 --- a/src/playback/internal/playbackuiactions.cpp +++ b/src/playback/internal/playbackuiactions.cpp @@ -143,6 +143,17 @@ const UiActionList PlaybackUiActions::m_settingsActions = { // ), }; +const UiActionList PlaybackUiActions::m_hearPlaybackWhenEditingActions = { + UiAction("toggle-hear-playback-when-editing", + mu::context::UiCtxAny, + mu::context::CTX_ANY, + TranslatableString("action", "Toggle hear playback when editing"), + TranslatableString("action", "Toggle hear playback when editing"), + IconCode::Code::EDIT, + Checkable::Yes + ), +}; + const UiActionList PlaybackUiActions::m_loopBoundaryActions = { UiAction("loop-in", mu::context::UiCtxAny, @@ -190,6 +201,7 @@ const UiActionList& PlaybackUiActions::actionsList() const alist.insert(alist.end(), m_midiInputActions.cbegin(), m_midiInputActions.cend()); alist.insert(alist.end(), m_midiInputPitchActions.cbegin(), m_midiInputPitchActions.cend()); alist.insert(alist.end(), m_settingsActions.cbegin(), m_settingsActions.cend()); + alist.insert(alist.end(), m_hearPlaybackWhenEditingActions.cbegin(), m_hearPlaybackWhenEditingActions.cend()); alist.insert(alist.end(), m_loopBoundaryActions.cbegin(), m_loopBoundaryActions.cend()); } return alist; @@ -243,6 +255,11 @@ const UiActionList& PlaybackUiActions::loopBoundaryActions() return m_loopBoundaryActions; } +const UiActionList& PlaybackUiActions::hearPlaybackWhenEditingActions() +{ + return m_hearPlaybackWhenEditingActions; +} + const muse::ui::ToolConfig& PlaybackUiActions::defaultPlaybackToolConfig() { static ToolConfig config; diff --git a/src/playback/internal/playbackuiactions.h b/src/playback/internal/playbackuiactions.h index f3ab0f98b63cb..4a187bb468c1d 100644 --- a/src/playback/internal/playbackuiactions.h +++ b/src/playback/internal/playbackuiactions.h @@ -50,6 +50,7 @@ class PlaybackUiActions : public muse::ui::IUiActionsModule, public muse::async: static const muse::ui::UiActionList& midiInputActions(); static const muse::ui::UiActionList& midiInputPitchActions(); static const muse::ui::UiActionList& settingsActions(); + static const muse::ui::UiActionList& hearPlaybackWhenEditingActions(); static const muse::ui::UiActionList& loopBoundaryActions(); static const muse::ui::ToolConfig& defaultPlaybackToolConfig(); @@ -60,6 +61,7 @@ class PlaybackUiActions : public muse::ui::IUiActionsModule, public muse::async: static const muse::ui::UiActionList m_midiInputPitchActions; static const muse::ui::UiActionList m_settingsActions; static const muse::ui::UiActionList m_loopBoundaryActions; + static const muse::ui::UiActionList m_hearPlaybackWhenEditingActions; std::shared_ptr m_controller; muse::async::Channel m_actionEnabledChanged; diff --git a/src/playback/iplaybackconfiguration.h b/src/playback/iplaybackconfiguration.h index 562a830e03e95..054aa2cd1d66a 100644 --- a/src/playback/iplaybackconfiguration.h +++ b/src/playback/iplaybackconfiguration.h @@ -43,6 +43,8 @@ class IPlaybackConfiguration : MODULE_EXPORT_INTERFACE virtual bool playHarmonyWhenEditing() const = 0; virtual void setPlayHarmonyWhenEditing(bool value) = 0; + virtual muse::async::Notification playNotesWhenEditingChanged() const = 0; + virtual PlaybackCursorType cursorType() const = 0; virtual bool isMixerSectionVisible(MixerSectionType sectionType) const = 0; diff --git a/src/playback/iplaybackcontroller.h b/src/playback/iplaybackcontroller.h index c1d277ab26bbb..b5e99eaaf2d42 100644 --- a/src/playback/iplaybackcontroller.h +++ b/src/playback/iplaybackcontroller.h @@ -101,6 +101,8 @@ class IPlaybackController : MODULE_EXPORT_INTERFACE virtual void setNotation(notation::INotationPtr notation) = 0; virtual void setIsExportingAudio(bool exporting) = 0; + + virtual void toggleHearPlaybackWhenEditing() = 0; }; } diff --git a/src/playback/tests/mocks/playbackcontrollermock.h b/src/playback/tests/mocks/playbackcontrollermock.h index 716724e53c392..ed423474e88dc 100644 --- a/src/playback/tests/mocks/playbackcontrollermock.h +++ b/src/playback/tests/mocks/playbackcontrollermock.h @@ -87,6 +87,8 @@ class PlaybackControllerMock : public IPlaybackController MOCK_METHOD(void, setNotation, (notation::INotationPtr), (override)); MOCK_METHOD(void, setIsExportingAudio, (bool), (override)); + + MOCK_METHOD(void, toggleHearPlaybackWhenEditing, (), (override)); }; } diff --git a/src/playback/view/playbacktoolbarmodel.cpp b/src/playback/view/playbacktoolbarmodel.cpp index f23477da80018..ac52d827f3cf0 100644 --- a/src/playback/view/playbacktoolbarmodel.cpp +++ b/src/playback/view/playbacktoolbarmodel.cpp @@ -106,6 +106,14 @@ void PlaybackToolBarModel::updateActions() settingsItems << makeMenuItem(action.code); } + settingsItems << makeSeparator(); + + for (const UiAction& action : PlaybackUiActions::hearPlaybackWhenEditingActions()) { + settingsItems << makeMenuItem(action.code); + } + + settingsItems << makeSeparator(); + if (!m_isToolbarFloating) { settingsItems << makeSeparator(); } diff --git a/src/stubs/playback/playbackcontrollerstub.cpp b/src/stubs/playback/playbackcontrollerstub.cpp index 4a40d1fab7456..40d1e1192ae82 100644 --- a/src/stubs/playback/playbackcontrollerstub.cpp +++ b/src/stubs/playback/playbackcontrollerstub.cpp @@ -193,3 +193,7 @@ void PlaybackControllerStub::setNotation(notation::INotationPtr) void PlaybackControllerStub::setIsExportingAudio(bool) { } + +void PlaybackControllerStub::toggleHearPlaybackWhenEditing() +{ +} diff --git a/src/stubs/playback/playbackcontrollerstub.h b/src/stubs/playback/playbackcontrollerstub.h index 51118c48a8aff..ddbd3adc48a4a 100644 --- a/src/stubs/playback/playbackcontrollerstub.h +++ b/src/stubs/playback/playbackcontrollerstub.h @@ -83,6 +83,8 @@ class PlaybackControllerStub : public IPlaybackController void setNotation(notation::INotationPtr notation) override; void setIsExportingAudio(bool exporting) override; + + void toggleHearPlaybackWhenEditing() override; }; }