diff --git a/src/appshell/view/preferences/noteinputpreferencesmodel.cpp b/src/appshell/view/preferences/noteinputpreferencesmodel.cpp index 3637bb07d9936..3f18d03386b2c 100644 --- a/src/appshell/view/preferences/noteinputpreferencesmodel.cpp +++ b/src/appshell/view/preferences/noteinputpreferencesmodel.cpp @@ -124,6 +124,7 @@ void NoteInputPreferencesModel::setPlayNotesWhenEditing(bool value) playbackConfiguration()->setPlayNotesWhenEditing(value); emit playNotesWhenEditingChanged(value); + playbackController()->toggleHearPlaybackWhenEditing(); } void NoteInputPreferencesModel::setNotePlayDurationMilliseconds(int duration) diff --git a/src/appshell/view/preferences/noteinputpreferencesmodel.h b/src/appshell/view/preferences/noteinputpreferencesmodel.h index 78c77ea6da1ee..56120816e07a4 100644 --- a/src/appshell/view/preferences/noteinputpreferencesmodel.h +++ b/src/appshell/view/preferences/noteinputpreferencesmodel.h @@ -29,6 +29,7 @@ #include "shortcuts/ishortcutsconfiguration.h" #include "notation/inotationconfiguration.h" #include "playback/iplaybackconfiguration.h" +#include "playback/iplaybackcontroller.h" namespace mu::appshell { class NoteInputPreferencesModel : public QObject, public muse::Injectable @@ -57,6 +58,7 @@ class NoteInputPreferencesModel : public QObject, public muse::Injectable muse::Inject notationConfiguration = { this }; muse::Inject playbackConfiguration = { this }; muse::Inject engravingConfiguration = { this }; + muse::Inject playbackController = { }; public: explicit NoteInputPreferencesModel(QObject* parent = nullptr); diff --git a/src/notation/internal/notationuiactions.cpp b/src/notation/internal/notationuiactions.cpp index 083c97e70d587..ce202dc3c6a2e 100644 --- a/src/notation/internal/notationuiactions.cpp +++ b/src/notation/internal/notationuiactions.cpp @@ -566,8 +566,8 @@ const UiActionList NotationUiActions::m_actions = { UiAction("measures-per-system", mu::context::UiCtxProjectOpened, mu::context::CTX_NOTATION_OPENED, - TranslatableString("action", "Measures per s&ystem…"), - TranslatableString("action", "Measures per system…") + TranslatableString("action", "Measures per s&ystem…"), + TranslatableString("action", "Measures per system…") ), UiAction("undo", mu::context::UiCtxProjectOpened, @@ -2042,6 +2042,14 @@ const UiActionList NotationUiActions::m_actions = { IconCode::Code::EDIT, Checkable::Yes ), + 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 + ), UiAction("toggle-insert-mode", mu::context::UiCtxProjectOpened, mu::context::CTX_ANY, diff --git a/src/playback/internal/playbackcontroller.cpp b/src/playback/internal/playbackcontroller.cpp index daa99f461276c..4c530f95a4109 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(); @@ -141,6 +143,7 @@ void PlaybackController::init() }); m_measureInputLag = configuration()->shouldMeasureInputLag(); + m_hearPlaybackWhenEditing = configuration()->playNotesWhenEditing(); } void PlaybackController::updateCurrentTempo() @@ -1436,7 +1439,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 +1635,15 @@ muse::audio::secs_t PlaybackController::playedTickToSecs(int tick) const { return secs_t(notationPlayback()->playedTickToSec(tick)); } + +void PlaybackController::toggleHearPlaybackWhenEditing() +{ + // Just to check if the function has been called from noteinputpreferencesmodel or from playbackcontroller + // If the configuration() stored value is the same as the local value we have been called from playbackcontroller to change the value + if (m_hearPlaybackWhenEditing == configuration()->playNotesWhenEditing()) { + configuration()->setPlayNotesWhenEditing(!m_hearPlaybackWhenEditing); + } + m_hearPlaybackWhenEditing = !m_hearPlaybackWhenEditing; + + notifyActionCheckedChanged(TOGGLE_HEAR_PLAYBACK_WHEN_EDITING); +} diff --git a/src/playback/internal/playbackcontroller.h b/src/playback/internal/playbackcontroller.h index 78262d878dfbe..4fce01b701869 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; @@ -241,6 +244,8 @@ class PlaybackController : public IPlaybackController, public muse::actions::Act DrumsetLoader m_drumsetLoader; bool m_measureInputLag = false; + + bool m_hearPlaybackWhenEditing; }; } 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/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; }; }