Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch PianoKeyboard between Notated Pitch (effective pitch) and Playback Pitch (completed). #24784

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
4 changes: 2 additions & 2 deletions src/engraving/dom/cmd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3384,7 +3384,7 @@ void Score::cmdMoveLyrics(Lyrics* lyrics, DirectionV dir)
// realtimeAdvance
//---------------------------------------------------------

void Score::realtimeAdvance()
void Score::realtimeAdvance(bool allowTransposition)
{
InputState& is = inputState();
if (!is.noteEntryMode()) {
Expand All @@ -3410,7 +3410,7 @@ void Score::realtimeAdvance()
Chord* prevChord = prevCR->isChord() ? toChord(prevCR) : 0;
bool partOfChord = false;
for (const MidiInputEvent& ev : midiPitches) {
addTiedMidiPitch(ev.pitch, partOfChord, prevChord);
addTiedMidiPitch(ev.pitch, partOfChord, prevChord, allowTransposition);
partOfChord = true;
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/engraving/dom/edit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1560,9 +1560,9 @@ void Score::cmdRemoveTimeSig(TimeSig* ts)
// addTiedMidiPitch
//---------------------------------------------------------

Note* Score::addTiedMidiPitch(int pitch, bool addFlag, Chord* prevChord)
Note* Score::addTiedMidiPitch(int pitch, bool addFlag, Chord* prevChord, bool allowTransposition)
{
Note* n = addMidiPitch(pitch, addFlag);
Note* n = addMidiPitch(pitch, addFlag, allowTransposition);
if (prevChord) {
Note* nn = prevChord->findNote(n->pitch());
if (nn) {
Expand All @@ -1580,14 +1580,14 @@ Note* Score::addTiedMidiPitch(int pitch, bool addFlag, Chord* prevChord)
return n;
}

NoteVal Score::noteVal(int pitch) const
NoteVal Score::noteVal(int pitch, bool allowTransposition) const
{
NoteVal nval(pitch);
Staff* st = staff(inputState().track() / VOICES);

// if transposing, interpret MIDI pitch as representing desired written pitch
// set pitch based on corresponding sounding pitch
if (!style().styleB(Sid::concertPitch)) {
if (!style().styleB(Sid::concertPitch) && allowTransposition) {
nval.pitch += st->part()->instrument(inputState().tick())->transpose().chromatic;
}
// let addPitch calculate tpc values from pitch
Expand All @@ -1601,9 +1601,9 @@ NoteVal Score::noteVal(int pitch) const
// addMidiPitch
//---------------------------------------------------------

Note* Score::addMidiPitch(int pitch, bool addFlag)
Note* Score::addMidiPitch(int pitch, bool addFlag, bool allowTransposition)
{
NoteVal nval = noteVal(pitch);
NoteVal nval = noteVal(pitch, allowTransposition);
return addPitch(nval, addFlag);
}

Expand Down
8 changes: 4 additions & 4 deletions src/engraving/dom/score.h
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ class Score : public EngravingObject, public muse::Injectable
void cmdMoveRest(Rest*, DirectionV);
void cmdMoveLyrics(Lyrics*, DirectionV);

void realtimeAdvance();
void realtimeAdvance(bool allowTransposition);

void addRemoveBreaks(int interval, bool lock);

Expand Down Expand Up @@ -497,9 +497,9 @@ class Score : public EngravingObject, public muse::Injectable
bool containsElement(const EngravingItem*) const;

Note* addPitch(NoteVal&, bool addFlag, InputState* externalInputState = nullptr);
Note* addTiedMidiPitch(int pitch, bool addFlag, Chord* prevChord);
NoteVal noteVal(int pitch) const;
Note* addMidiPitch(int pitch, bool addFlag);
Note* addTiedMidiPitch(int pitch, bool addFlag, Chord* prevChord, bool allowTransposition);
NoteVal noteVal(int pitch, bool allowTransposition) const;
Note* addMidiPitch(int pitch, bool addFlag, bool allowTransposition);
Note* addNote(Chord*, const NoteVal& noteVal, bool forceAccidental = false, const std::set<SymId>& articulationIds = {},
InputState* externalInputState = nullptr);
Note* addNoteToTiedChord(Chord*, const NoteVal& noteVal, bool forceAccidental = false, const std::set<SymId>& articulationIds = {});
Expand Down
3 changes: 3 additions & 0 deletions src/notation/inotationconfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ class INotationConfiguration : MODULE_EXPORT_INTERFACE
virtual muse::ValCh<int> pianoKeyboardNumberOfKeys() const = 0;
virtual void setPianoKeyboardNumberOfKeys(int number) = 0;

virtual muse::ValCh<bool> midiUseWrittenPitch() const = 0;
virtual void setMidiUseWrittenPitch(bool useWrittenPitch) = 0;

// TODO: Delete when the new percussion panel is finished
virtual bool useNewPercussionPanel() const = 0;
virtual void setUseNewPercussionPanel(bool use) = 0;
Expand Down
17 changes: 17 additions & 0 deletions src/notation/internal/notationconfiguration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ static const Settings::Key MOUSE_ZOOM_PRECISION(module_name, "ui/canvas/zoomPrec
static const Settings::Key USER_STYLES_PATH(module_name, "application/paths/myStyles");

static const Settings::Key IS_MIDI_INPUT_ENABLED(module_name, "io/midi/enableInput");
static const Settings::Key USE_MIDI_INPUT_WRITTEN_PITCH(module_name, "io/midi/useWrittenPitch");
static const Settings::Key IS_AUTOMATICALLY_PAN_ENABLED(module_name, "application/playback/panPlayback");
static const Settings::Key PLAYBACK_SMOOTH_PANNING(module_name, "application/playback/smoothPan");
static const Settings::Key IS_PLAY_REPEATS_ENABLED(module_name, "application/playback/playRepeats");
Expand Down Expand Up @@ -220,6 +221,12 @@ void NotationConfiguration::init()
m_pianoKeyboardNumberOfKeys.set(val.toInt());
});

settings()->setDefaultValue(USE_MIDI_INPUT_WRITTEN_PITCH, Val(true));
m_midiInputUseWrittenPitch.val = settings()->value(USE_MIDI_INPUT_WRITTEN_PITCH).toBool();
settings()->valueChanged(USE_MIDI_INPUT_WRITTEN_PITCH).onReceive(this, [this](const Val& val) {
m_midiInputUseWrittenPitch.set(val.toBool());
});

settings()->setDefaultValue(USE_NEW_PERCUSSION_PANEL_KEY, Val(false));
settings()->setDefaultValue(AUTO_SHOW_PERCUSSION_PANEL_KEY, Val(true));

Expand Down Expand Up @@ -919,6 +926,16 @@ void NotationConfiguration::setPianoKeyboardNumberOfKeys(int number)
settings()->setSharedValue(PIANO_KEYBOARD_NUMBER_OF_KEYS, Val(number));
}

ValCh<bool> NotationConfiguration::midiUseWrittenPitch() const
{
return m_midiInputUseWrittenPitch;
}

void NotationConfiguration::setMidiUseWrittenPitch(bool useWrittenPitch)
{
settings()->setSharedValue(USE_MIDI_INPUT_WRITTEN_PITCH, Val(useWrittenPitch));
}

muse::io::path_t NotationConfiguration::firstScoreOrderListPath() const
{
return settings()->value(FIRST_SCORE_ORDER_LIST_KEY).toString();
Expand Down
4 changes: 4 additions & 0 deletions src/notation/internal/notationconfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ class NotationConfiguration : public INotationConfiguration, public muse::async:
muse::ValCh<int> pianoKeyboardNumberOfKeys() const override;
void setPianoKeyboardNumberOfKeys(int number) override;

muse::ValCh<bool> midiUseWrittenPitch() const override;
void setMidiUseWrittenPitch(bool useWrittenPitch) override;

bool useNewPercussionPanel() const override;
void setUseNewPercussionPanel(bool use) override;

Expand Down Expand Up @@ -231,6 +234,7 @@ class NotationConfiguration : public INotationConfiguration, public muse::async:
muse::async::Notification m_isPlayRepeatsChanged;
muse::async::Notification m_isPlayChordSymbolsChanged;
muse::ValCh<int> m_pianoKeyboardNumberOfKeys;
muse::ValCh<bool> m_midiInputUseWrittenPitch;
muse::async::Channel<QColor> m_anchorColorChanged;

int m_styleDialogLastPageIndex = 0;
Expand Down
6 changes: 3 additions & 3 deletions src/notation/internal/notationmidiinput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ Note* NotationMidiInput::addNoteToScore(const muse::midi::Event& e)
}
}

mu::engraving::Note* note = sc->addMidiPitch(inputEv.pitch, inputEv.chord);
mu::engraving::Note* note = sc->addMidiPitch(inputEv.pitch, inputEv.chord, configuration()->midiUseWrittenPitch().val);

sc->activeMidiPitches().push_back(inputEv);

Expand Down Expand Up @@ -250,7 +250,7 @@ Note* NotationMidiInput::makeNote(const muse::midi::Event& e)
note->setParent(chord);
note->setStaffIdx(engraving::track2staff(inputState.cr()->track()));

engraving::NoteVal nval = score->noteVal(e.note());
engraving::NoteVal nval = score->noteVal(e.note(), configuration()->midiUseWrittenPitch().val);
note->setNval(nval);

return note;
Expand Down Expand Up @@ -306,7 +306,7 @@ void NotationMidiInput::doRealtimeAdvance()

QTimer::singleShot(100, Qt::PreciseTimer, [this]() {
m_undoStack->prepareChanges();
m_getScore->score()->realtimeAdvance();
m_getScore->score()->realtimeAdvance(configuration()->midiUseWrittenPitch().val);
m_undoStack->commitChanges();
});

Expand Down
3 changes: 3 additions & 0 deletions src/notation/tests/mocks/notationconfigurationmock.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,9 @@ class NotationConfigurationMock : public INotationConfiguration
MOCK_METHOD(muse::ValCh<int>, pianoKeyboardNumberOfKeys, (), (const, override));
MOCK_METHOD(void, setPianoKeyboardNumberOfKeys, (int), (override));

MOCK_METHOD(muse::ValCh<bool>, midiUseWrittenPitch, (), (const, override));
MOCK_METHOD(void, setMidiUseWrittenPitch, (bool), (override));

MOCK_METHOD(bool, useNewPercussionPanel, (), (const, override));
MOCK_METHOD(void, setUseNewPercussionPanel, (bool), (override));

Expand Down
9 changes: 7 additions & 2 deletions src/notation/view/pianokeyboard/pianokeyboardcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -133,9 +133,9 @@ void PianoKeyboardController::updateNotesKeys(const std::vector<const Note*>& re
};

for (const mu::engraving::Note* note : receivedNotes) {
newKeys.insert(static_cast<piano_key_t>(note->epitch()));
newKeys.insert(static_cast<piano_key_t>(useWrittenPitch() ? note->epitch() : note->ppitch()));
for (const mu::engraving::Note* otherNote : note->chord()->notes()) {
newOtherNotesInChord.insert(static_cast<piano_key_t>(otherNote->epitch()));
newOtherNotesInChord.insert(static_cast<piano_key_t>(useWrittenPitch() ? otherNote->epitch() : otherNote->ppitch()));
}
}
}
Expand Down Expand Up @@ -175,3 +175,8 @@ INotationPtr PianoKeyboardController::currentNotation() const
{
return context()->currentNotation();
}

bool PianoKeyboardController::useWrittenPitch() const
{
return notationConfiguration()->midiUseWrittenPitch().val;
}
4 changes: 4 additions & 0 deletions src/notation/view/pianokeyboard/pianokeyboardcontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@

#include "modularity/ioc.h"
#include "context/iglobalcontext.h"
#include "inotationconfiguration.h"

#include "pianokeyboardtypes.h"

namespace mu::notation {
class PianoKeyboardController : public muse::Injectable, public muse::async::Asyncable
{
muse::Inject<INotationConfiguration> notationConfiguration = { this };
muse::Inject<context::IGlobalContext> context = { this };

public:
Expand All @@ -45,6 +47,8 @@ class PianoKeyboardController : public muse::Injectable, public muse::async::Asy

bool isFromMidi() const;

bool useWrittenPitch() const;

private:
INotationPtr currentNotation() const;

Expand Down
14 changes: 14 additions & 0 deletions src/playback/internal/playbackcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ static const ActionCode LOOP_IN_CODE("loop-in");
static const ActionCode LOOP_OUT_CODE("loop-out");
static const ActionCode METRONOME_CODE("metronome");
static const ActionCode MIDI_ON_CODE("midi-on");
static const ActionCode INPUT_WRITTEN_PITCH("midi-input-written-pitch");
static const ActionCode INPUT_SOUNDING_PITCH("midi-input-sounding-pitch");
static const ActionCode COUNT_IN_CODE("countin");
static const ActionCode PAN_CODE("pan");
static const ActionCode REPEAT_CODE("repeat");
Expand Down Expand Up @@ -107,6 +109,8 @@ void PlaybackController::init()
dispatcher()->reg(this, PAN_CODE, this, &PlaybackController::toggleAutomaticallyPan);
dispatcher()->reg(this, METRONOME_CODE, this, &PlaybackController::toggleMetronome);
dispatcher()->reg(this, MIDI_ON_CODE, this, &PlaybackController::toggleMidiInput);
dispatcher()->reg(this, INPUT_WRITTEN_PITCH, this, &PlaybackController::toggleMidiInputPitch);
dispatcher()->reg(this, INPUT_SOUNDING_PITCH, this, &PlaybackController::toggleMidiInputPitch);
dispatcher()->reg(this, COUNT_IN_CODE, this, &PlaybackController::toggleCountIn);
dispatcher()->reg(this, PLAYBACK_SETUP, this, &PlaybackController::openPlaybackSetupDialog);

Expand Down Expand Up @@ -728,6 +732,14 @@ void PlaybackController::toggleMidiInput()
notifyActionCheckedChanged(MIDI_ON_CODE);
}

void PlaybackController::toggleMidiInputPitch()
{
bool useWrittenPitch = notationConfiguration()->midiUseWrittenPitch().val;
notationConfiguration()->setMidiUseWrittenPitch(!useWrittenPitch);
notifyActionCheckedChanged(INPUT_WRITTEN_PITCH);
notifyActionCheckedChanged(INPUT_SOUNDING_PITCH);
}

void PlaybackController::toggleCountIn()
{
bool countInEnabled = notationConfiguration()->isCountInEnabled();
Expand Down Expand Up @@ -1401,6 +1413,8 @@ bool PlaybackController::actionChecked(const ActionCode& actionCode) const
QMap<std::string, bool> isChecked {
{ LOOP_CODE, isLoopEnabled() },
{ MIDI_ON_CODE, notationConfiguration()->isMidiInputEnabled() },
{ INPUT_WRITTEN_PITCH, notationConfiguration()->midiUseWrittenPitch().val },
{ INPUT_SOUNDING_PITCH, !notationConfiguration()->midiUseWrittenPitch().val },
{ REPEAT_CODE, notationConfiguration()->isPlayRepeatsEnabled() },
{ PLAY_CHORD_SYMBOLS_CODE, notationConfiguration()->isPlayChordSymbolsEnabled() },
{ PAN_CODE, notationConfiguration()->isAutomaticallyPanEnabled() },
Expand Down
1 change: 1 addition & 0 deletions src/playback/internal/playbackcontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ class PlaybackController : public IPlaybackController, public muse::actions::Act
void toggleAutomaticallyPan();
void toggleMetronome();
void toggleMidiInput();
void toggleMidiInputPitch();
void toggleCountIn();
void toggleLoopPlayback();

Expand Down
36 changes: 35 additions & 1 deletion src/playback/internal/playbackuiactions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ const UiActionList PlaybackUiActions::m_mainActions = {
)
};

const UiActionList PlaybackUiActions::m_settingsActions = {
const UiActionList PlaybackUiActions::m_midiInputActions = {
UiAction("midi-on",
mu::context::UiCtxAny,
mu::context::CTX_ANY,
Expand All @@ -87,6 +87,28 @@ const UiActionList PlaybackUiActions::m_settingsActions = {
IconCode::Code::MIDI_INPUT,
Checkable::Yes
),
};

const UiActionList PlaybackUiActions::m_midiInputPitchActions = {
UiAction("midi-input-written-pitch",
mu::context::UiCtxAny,
mu::context::CTX_ANY,
TranslatableString("action", "Written pitch"),
TranslatableString("action", "Input written pitch"),
IconCode::Code::NONE,
Checkable::Yes
),
UiAction("midi-input-sounding-pitch",
mu::context::UiCtxAny,
mu::context::CTX_ANY,
TranslatableString("action", "Sounding pitch"),
TranslatableString("action", "Input sounding pitch"),
IconCode::Code::NONE,
Checkable::Yes
),
};

const UiActionList PlaybackUiActions::m_settingsActions = {
UiAction("repeat",
mu::context::UiCtxAny,
mu::context::CTX_NOTATION_FOCUSED,
Expand Down Expand Up @@ -165,6 +187,8 @@ const UiActionList& PlaybackUiActions::actionsList() const
static UiActionList alist;
if (alist.empty()) {
alist.insert(alist.end(), m_mainActions.cbegin(), m_mainActions.cend());
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_loopBoundaryActions.cbegin(), m_loopBoundaryActions.cend());
}
Expand Down Expand Up @@ -199,6 +223,16 @@ muse::async::Channel<ActionCodeList> PlaybackUiActions::actionCheckedChanged() c
return m_actionCheckedChanged;
}

const UiActionList& PlaybackUiActions::midiInputActions()
{
return m_midiInputActions;
}

const UiActionList& PlaybackUiActions::midiInputPitchActions()
{
return m_midiInputPitchActions;
}

const UiActionList& PlaybackUiActions::settingsActions()
{
return m_settingsActions;
Expand Down
4 changes: 4 additions & 0 deletions src/playback/internal/playbackuiactions.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,17 @@ class PlaybackUiActions : public muse::ui::IUiActionsModule, public muse::async:
bool actionChecked(const muse::ui::UiAction& act) const override;
muse::async::Channel<muse::actions::ActionCodeList> actionCheckedChanged() const override;

static const muse::ui::UiActionList& midiInputActions();
static const muse::ui::UiActionList& midiInputPitchActions();
static const muse::ui::UiActionList& settingsActions();
static const muse::ui::UiActionList& loopBoundaryActions();

static const muse::ui::ToolConfig& defaultPlaybackToolConfig();

private:
static const muse::ui::UiActionList m_mainActions;
static const muse::ui::UiActionList m_midiInputActions;
static const muse::ui::UiActionList m_midiInputPitchActions;
static const muse::ui::UiActionList m_settingsActions;
static const muse::ui::UiActionList m_loopBoundaryActions;

Expand Down
23 changes: 23 additions & 0 deletions src/playback/view/playbacktoolbarmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,13 @@ void PlaybackToolBarModel::updateActions()
MenuItemList result;
MenuItemList settingsItems;

for (const UiAction& action : PlaybackUiActions::midiInputActions()) {
settingsItems << makeMenuItem(action.code);
}

settingsItems << makeInputPitchMenu();
settingsItems << makeSeparator();

for (const UiAction& action : PlaybackUiActions::settingsActions()) {
settingsItems << makeMenuItem(action.code);
}
Expand Down Expand Up @@ -131,6 +138,22 @@ void PlaybackToolBarModel::updateActions()
setItems(result);
}

MenuItem* PlaybackToolBarModel::makeInputPitchMenu()
{
MenuItemList items;

for (const UiAction& action : PlaybackUiActions::midiInputPitchActions()) {
items << makeMenuItem(action.code);
}

MenuItem* menu = makeMenu(muse::TranslatableString("notation", "Input pitch"), items);
UiAction action = menu->action();
action.iconCode = IconCode::Code::MUSIC_NOTES;
menu->setAction(action);

return menu;
}

void PlaybackToolBarModel::onActionsStateChanges(const ActionCodeList& codes)
{
AbstractMenuModel::onActionsStateChanges(codes);
Expand Down
Loading