From d59cd4d802f03605403bd5df4dfa78271d1ff58d Mon Sep 17 00:00:00 2001 From: Calum Matheson Date: Tue, 25 Feb 2025 10:14:26 +0000 Subject: [PATCH 1/5] Minor refactor - flatten nesting --- src/engraving/dom/midimapping.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/engraving/dom/midimapping.cpp b/src/engraving/dom/midimapping.cpp index 6270d7d1712ac..c00f21b2c52f4 100644 --- a/src/engraving/dom/midimapping.cpp +++ b/src/engraving/dom/midimapping.cpp @@ -190,14 +190,17 @@ void MasterScore::reorderMidiMapping() for (const auto& pair : part->instruments()) { const Instrument* instr = pair.second; for (InstrChannel* channel : instr->channel()) { - if (!(m_midiMapping[sequenceNumber].part() == part - && m_midiMapping[sequenceNumber].m_masterChannel == channel)) { - int shouldBe = channel->channel(); - swap(m_midiMapping[sequenceNumber], m_midiMapping[shouldBe]); - m_midiMapping[sequenceNumber].articulation()->setChannel(sequenceNumber); - channel->setChannel(sequenceNumber); - m_midiMapping[shouldBe].articulation()->setChannel(shouldBe); + if (m_midiMapping[sequenceNumber].part() == part && m_midiMapping[sequenceNumber].m_masterChannel == channel) { + sequenceNumber++; + continue; } + + const int shouldBe = channel->channel(); + swap(m_midiMapping[sequenceNumber], m_midiMapping[shouldBe]); + m_midiMapping[sequenceNumber].articulation()->setChannel(sequenceNumber); + channel->setChannel(sequenceNumber); + m_midiMapping[shouldBe].articulation()->setChannel(shouldBe); + sequenceNumber++; } } From 471b77ce701010e648ca4f328ed0e262053456d9 Mon Sep 17 00:00:00 2001 From: Calum Matheson Date: Thu, 27 Feb 2025 11:23:08 +0000 Subject: [PATCH 2/5] Refactor updateMidiMapping --- src/engraving/dom/masterscore.h | 3 + src/engraving/dom/midimapping.cpp | 103 +++++++++++++++++------------- 2 files changed, 60 insertions(+), 46 deletions(-) diff --git a/src/engraving/dom/masterscore.h b/src/engraving/dom/masterscore.h index bc48661f2beab..ab35f043aa62f 100644 --- a/src/engraving/dom/masterscore.h +++ b/src/engraving/dom/masterscore.h @@ -199,7 +199,10 @@ class MasterScore : public Score void reorderMidiMapping(); void rebuildExcerptsMidiMapping(); void removeDeletedMidiMapping(); + int updateMidiMapping(); + void doUpdateMidiMapping(int& maxport, std::set& occupiedMidiChannels, unsigned int& searchMidiMappingFrom, Part* part, + InstrChannel* channel, bool useDrumset); friend class EngravingProject; friend class compat::ScoreAccess; diff --git a/src/engraving/dom/midimapping.cpp b/src/engraving/dom/midimapping.cpp index c00f21b2c52f4..b97e23520fb81 100644 --- a/src/engraving/dom/midimapping.cpp +++ b/src/engraving/dom/midimapping.cpp @@ -259,8 +259,8 @@ void MasterScore::removeDeletedMidiMapping() int MasterScore::updateMidiMapping() { int maxport = 0; - std::set occupiedMidiChannels;// each entry is port*16+channel, port range: 0-inf, channel: 0-15 - unsigned int searchMidiMappingFrom = 0; // makes getting next free MIDI mapping faster + std::set occupiedMidiChannels; // each entry is port*16+channel, port range: 0-inf, channel: 0-15 + unsigned int searchMidiMappingFrom = 0; // makes getting next free MIDI mapping faster for (const MidiMapping& mm :m_midiMapping) { if (mm.port() == -1 || mm.channel() == -1) { @@ -275,56 +275,67 @@ int MasterScore::updateMidiMapping() for (Part* part : parts()) { for (const auto& pair : part->instruments()) { const Instrument* instr = pair.second; - bool drum = instr->useDrumset(); + const bool useDrumset = instr->useDrumset(); for (InstrChannel* channel : instr->channel()) { - bool channelExists = false; - for (const MidiMapping& mapping: m_midiMapping) { - if (channel == mapping.m_masterChannel && channel->channel() != -1) { - channelExists = true; - break; - } - } - // Channel could already exist, but have unassigned port or channel. Repair and continue - if (channelExists) { - if (m_midiMapping[channel->channel()].port() == -1) { - const int nm - = getNextFreeMidiMapping(occupiedMidiChannels, searchMidiMappingFrom, -1, - m_midiMapping[channel->channel()].channel()); - m_midiMapping[channel->channel()].m_port = nm / 16; - } else if (m_midiMapping[channel->channel()].channel() == -1) { - if (drum) { - m_midiMapping[channel->channel()].m_port = getNextFreeDrumMidiMapping(occupiedMidiChannels) / 16; - m_midiMapping[channel->channel()].m_channel = 9; - continue; - } - int nm = getNextFreeMidiMapping(occupiedMidiChannels, searchMidiMappingFrom, - m_midiMapping[channel->channel()].port()); - m_midiMapping[channel->channel()].m_port = nm / 16; - m_midiMapping[channel->channel()].m_channel = nm % 16; - } - continue; - } + doUpdateMidiMapping(maxport, occupiedMidiChannels, searchMidiMappingFrom, part, channel, useDrumset); + } + } + } - int midiPort; - int midiChannel; - if (drum) { - midiPort = getNextFreeDrumMidiMapping(occupiedMidiChannels) / 16; - midiChannel = 9; - } else { - int nm = getNextFreeMidiMapping(occupiedMidiChannels, searchMidiMappingFrom); - midiPort = nm / 16; - midiChannel = nm % 16; - } + return maxport; +} - if (midiPort > maxport) { - maxport = midiPort; - } +void MasterScore::doUpdateMidiMapping(int& maxport, std::set& occupiedMidiChannels, unsigned int& searchMidiMappingFrom, + Part* part, InstrChannel* channel, bool useDrumset) +{ + bool channelExists = false; + for (const MidiMapping& mapping : m_midiMapping) { + if (channel == mapping.m_masterChannel && channel->channel() != -1) { + channelExists = true; + break; + } + } - addMidiMapping(channel, part, midiPort, midiChannel); - } + if (!channelExists) { + int midiPort; + int midiChannel; + + if (useDrumset) { + midiPort = getNextFreeDrumMidiMapping(occupiedMidiChannels) / 16; + midiChannel = 9; + } else { + const int nm = getNextFreeMidiMapping(occupiedMidiChannels, searchMidiMappingFrom); + midiPort = nm / 16; + midiChannel = nm % 16; + } + + if (midiPort > maxport) { + maxport = midiPort; } + + addMidiMapping(channel, part, midiPort, midiChannel); + return; + } + + // Channel could already exist, but have unassigned port or channel... + MidiMapping& mapping = m_midiMapping.at(channel->channel()); + + if (mapping.port() == -1) { + const int nm = getNextFreeMidiMapping(occupiedMidiChannels, searchMidiMappingFrom, -1, mapping.channel()); + mapping.m_port = nm / 16; + return; + } + + if (m_midiMapping[channel->channel()].channel() == -1) { + if (useDrumset) { + mapping.m_port = getNextFreeDrumMidiMapping(occupiedMidiChannels) / 16; + mapping.m_channel = 9; + return; + } + const int nm = getNextFreeMidiMapping(occupiedMidiChannels, searchMidiMappingFrom, mapping.port()); + mapping.m_port = nm / 16; + mapping.m_channel = nm % 16; } - return maxport; } //--------------------------------------------------------- From a266e4d70f2ba22262013571036a7f0c444e6a6c Mon Sep 17 00:00:00 2001 From: Calum Matheson Date: Thu, 27 Feb 2025 11:23:37 +0000 Subject: [PATCH 3/5] Fix crash relating to mmrests and inst changes --- src/engraving/dom/midimapping.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/engraving/dom/midimapping.cpp b/src/engraving/dom/midimapping.cpp index b97e23520fb81..ac36a53cac599 100644 --- a/src/engraving/dom/midimapping.cpp +++ b/src/engraving/dom/midimapping.cpp @@ -290,7 +290,8 @@ void MasterScore::doUpdateMidiMapping(int& maxport, std::set& occupiedMidiC { bool channelExists = false; for (const MidiMapping& mapping : m_midiMapping) { - if (channel == mapping.m_masterChannel && channel->channel() != -1) { + const bool validChannelIndex = channel->channel() >= 0 && channel->channel() < static_cast(m_midiMapping.size()); + if (channel == mapping.m_masterChannel && validChannelIndex) { channelExists = true; break; } From 8458d83b2e713b4c42291853550786d1b03c2a67 Mon Sep 17 00:00:00 2001 From: Calum Matheson Date: Thu, 27 Feb 2025 16:51:31 +0000 Subject: [PATCH 4/5] Don't auto show the percussion panel if piano keyboard is in use --- src/appshell/view/notationpagemodel.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/appshell/view/notationpagemodel.cpp b/src/appshell/view/notationpagemodel.cpp index 338fab3cfc895..5952efcedcc92 100644 --- a/src/appshell/view/notationpagemodel.cpp +++ b/src/appshell/view/notationpagemodel.cpp @@ -234,8 +234,10 @@ void NotationPageModel::updatePercussionPanelVisibility() { TRACEFUNC; + //! NOTE: If the user is entering percussion notes with the piano keyboard, we can assume that they + //! don't want the percussion panel to auto-show... const muse::dock::IDockWindow* window = dockWindowProvider()->window(); - if (!window) { + if (!window || window->isDockOpenAndCurrentInFrame(PIANO_KEYBOARD_PANEL_NAME)) { return; } From dbeaefa569a78e56cfa6d789190d28045aafa702 Mon Sep 17 00:00:00 2001 From: Calum Matheson Date: Wed, 26 Feb 2025 14:19:13 +0000 Subject: [PATCH 5/5] Fix ShadowNotes not responding to instrument changes --- src/notation/internal/notationinteraction.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/notation/internal/notationinteraction.cpp b/src/notation/internal/notationinteraction.cpp index 1eea8a939dfb3..9120ed7960c66 100644 --- a/src/notation/internal/notationinteraction.cpp +++ b/src/notation/internal/notationinteraction.cpp @@ -417,7 +417,6 @@ bool NotationInteraction::showShadowNote(ShadowNote& shadowNote, ShadowNoteParam const mu::engraving::InputState& inputState = score()->inputState(); const Staff* staff = score()->staff(position.staffIdx); - const mu::engraving::Instrument* instr = staff->part()->instrument(); mu::engraving::Segment* segment = position.segment; qreal segmentSkylineTopY = 0; @@ -433,6 +432,8 @@ bool NotationInteraction::showShadowNote(ShadowNote& shadowNote, ShadowNoteParam Fraction tick = segment->tick(); qreal mag = staff->staffMag(tick); + const mu::engraving::Instrument* instr = staff->part()->instrument(tick); + // in any empty measure, pos will be right next to barline // so pad this by barNoteDistance qreal relX = position.pos.x() - position.segment->measure()->canvasPos().x();