diff --git a/src/app/configs/data/shortcuts.xml b/src/app/configs/data/shortcuts.xml
index f3e9ee6d557e0..0182ecc05c6a6 100644
--- a/src/app/configs/data/shortcuts.xml
+++ b/src/app/configs/data/shortcuts.xml
@@ -819,6 +819,16 @@
notation-select-all
Ctrl+A
+
+ unmute-all
+ Ctrl+Shift+U
+ 0
+
+
+ unsolo-all
+ Ctrl+Shift+L
+ 0
+
system-break
Return
diff --git a/src/app/configs/data/shortcuts_azerty.xml b/src/app/configs/data/shortcuts_azerty.xml
index 20d115574481e..6410864603879 100644
--- a/src/app/configs/data/shortcuts_azerty.xml
+++ b/src/app/configs/data/shortcuts_azerty.xml
@@ -860,6 +860,16 @@
notation-select-all
Ctrl+A
+
+ unmute-all
+ Ctrl+Shift+U
+ 0
+
+
+ unsolo-all
+ Ctrl+Shift+L
+ 0
+
system-break
Return
diff --git a/src/app/configs/data/shortcuts_mac.xml b/src/app/configs/data/shortcuts_mac.xml
index 3acba86c3dde0..2cf4212f22c98 100644
--- a/src/app/configs/data/shortcuts_mac.xml
+++ b/src/app/configs/data/shortcuts_mac.xml
@@ -819,6 +819,16 @@
notation-select-all
Ctrl+A
+
+ unmute-all
+ Ctrl+Shift+U
+ 0
+
+
+ unsolo-all
+ Ctrl+Shift+L
+ 0
+
system-break
Return
diff --git a/src/playback/internal/playbackconfiguration.cpp b/src/playback/internal/playbackconfiguration.cpp
index d408abd40a520..4f52f21561229 100644
--- a/src/playback/internal/playbackconfiguration.cpp
+++ b/src/playback/internal/playbackconfiguration.cpp
@@ -51,6 +51,7 @@ static const Settings::Key MIXER_VOLUME_SECTION_VISIBLE_KEY(moduleName, "playbac
static const Settings::Key MIXER_FADER_SECTION_VISIBLE_KEY(moduleName, "playback/mixer/faderSectionVisible");
static const Settings::Key MIXER_MUTE_AND_SOLO_SECTION_VISIBLE_KEY(moduleName, "playback/mixer/muteAndSoloSectionVisible");
static const Settings::Key MIXER_TITLE_SECTION_VISIBLE_KEY(moduleName, "playback/mixer/titleSectionVisible");
+static const Settings::Key MIXER_UNMUTE_AND_UNSOLO_SECTION_VISIBLE_KEY(moduleName, "playback/mixer/unMuteAndUnSoloSectionVisible");
static const Settings::Key MIXER_RESET_SOUND_FLAGS_WHEN_CHANGE_SOUND_WARNING(moduleName,
"playback/mixer/needToShowAboutResetSoundFlagsWhwnChangeSoundWarning");
@@ -78,6 +79,7 @@ static Settings::Key mixerSectionVisibleKey(MixerSectionType sectionType)
case MixerSectionType::Fader: return MIXER_FADER_SECTION_VISIBLE_KEY;
case MixerSectionType::MuteAndSolo: return MIXER_MUTE_AND_SOLO_SECTION_VISIBLE_KEY;
case MixerSectionType::Title: return MIXER_TITLE_SECTION_VISIBLE_KEY;
+ case MixerSectionType::UnMuteAndUnSolo: return MIXER_UNMUTE_AND_UNSOLO_SECTION_VISIBLE_KEY;
case MixerSectionType::Unknown: break;
}
diff --git a/src/playback/internal/playbackcontroller.cpp b/src/playback/internal/playbackcontroller.cpp
old mode 100644
new mode 100755
index 54dd5ba15c4f4..fe00a269016bc
--- a/src/playback/internal/playbackcontroller.cpp
+++ b/src/playback/internal/playbackcontroller.cpp
@@ -69,6 +69,8 @@ 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_CODE("toggle-hear-playback-when-editing");
+static const ActionCode UNMUTE_ALL_CODE("unmute-all");
+static const ActionCode UNSOLO_ALL_CODE("unsolo-all");
static AudioOutputParams makeReverbOutputParams()
{
@@ -127,6 +129,8 @@ void PlaybackController::init()
dispatcher()->reg(this, PLAYBACK_SETUP, this, &PlaybackController::openPlaybackSetupDialog);
dispatcher()->reg(this, TOGGLE_HEAR_PLAYBACK_WHEN_EDITING_CODE, this, &PlaybackController::toggleHearPlaybackWhenEditing);
dispatcher()->reg(this, "playback-reload-cache", this, &PlaybackController::reloadPlaybackCache);
+ dispatcher()->reg(this, UNMUTE_ALL_CODE, this, &PlaybackController::unmuteAll);
+ dispatcher()->reg(this, UNSOLO_ALL_CODE, this, &PlaybackController::unsoloAll);
m_onlineSoundsController->regActions();
@@ -956,6 +960,41 @@ void PlaybackController::reloadPlaybackCache()
}
}
+void PlaybackController::unmuteAll()
+{
+ InstrumentTrackIdSet existingTrackIdSet = notationPlayback()->existingTrackIdSet();
+
+ for (const InstrumentTrackId& instrumentTrackId : existingTrackIdSet) {
+ if (instrumentTrackId == notationPlayback()->metronomeTrackId()) {
+ continue;
+ }
+
+ INotationSoloMuteState::SoloMuteState newState = m_notation->soloMuteState()->trackSoloMuteState(instrumentTrackId);
+ if (newState.mute == true) {
+ newState.mute = false;
+
+ setTrackSoloMuteState(instrumentTrackId, newState);
+ }
+ }
+
+ updateSoloMuteStates();
+}
+
+void PlaybackController::unsoloAll()
+{
+ InstrumentTrackIdSet existingTrackIdSet = notationPlayback()->existingTrackIdSet();
+
+ for (const InstrumentTrackId& instrumentTrackId : existingTrackIdSet) {
+ INotationSoloMuteState::SoloMuteState newState = trackSoloMuteState(instrumentTrackId);
+ if (newState.solo == true) {
+ newState.solo = false;
+ setTrackSoloMuteState(instrumentTrackId, newState);
+ }
+ }
+
+ updateSoloMuteStates();
+}
+
void PlaybackController::openPlaybackSetupDialog()
{
interactive()->open("musescore://playback/soundprofilesdialog");
diff --git a/src/playback/internal/playbackcontroller.h b/src/playback/internal/playbackcontroller.h
index bfd8184f19519..3fd302623831d 100644
--- a/src/playback/internal/playbackcontroller.h
+++ b/src/playback/internal/playbackcontroller.h
@@ -190,6 +190,8 @@ class PlaybackController : public IPlaybackController, public muse::actions::Act
void setMidiUseWrittenPitch(bool useWrittenPitch);
void toggleLoopPlayback();
void toggleHearPlaybackWhenEditing();
+ void unmuteAll();
+ void unsoloAll();
void reloadPlaybackCache();
diff --git a/src/playback/internal/playbackuiactions.cpp b/src/playback/internal/playbackuiactions.cpp
index 9899b2679d86b..96080c2487a6d 100644
--- a/src/playback/internal/playbackuiactions.cpp
+++ b/src/playback/internal/playbackuiactions.cpp
@@ -201,6 +201,19 @@ const UiActionList PlaybackUiActions::s_diagnosticActions = {
)
};
+const UiActionList PlaybackUiActions::s_mixerActions = {
+ UiAction("unmute-all",
+ mu::context::UiCtxAny,
+ mu::context::CTX_ANY,
+ TranslatableString("action", "Unmute All Channels")
+ ),
+ UiAction("unsolo-all",
+ mu::context::UiCtxAny,
+ mu::context::CTX_ANY,
+ TranslatableString("action", "Unsolo All Channels")
+ )
+};
+
const UiActionList PlaybackUiActions::s_onlineSoundsActions = {
UiAction(CLEAR_ONLINE_SOUNDS_CACHE_CODE,
mu::context::UiCtxAny,
@@ -264,6 +277,7 @@ const UiActionList& PlaybackUiActions::actionsList() const
alist.insert(alist.end(), s_settingsActions.cbegin(), s_settingsActions.cend());
alist.insert(alist.end(), s_loopBoundaryActions.cbegin(), s_loopBoundaryActions.cend());
alist.insert(alist.end(), s_diagnosticActions.cbegin(), s_diagnosticActions.cend());
+ alist.insert(alist.end(), s_mixerActions.cbegin(), s_mixerActions.cend());
alist.insert(alist.end(), s_onlineSoundsActions.cbegin(), s_onlineSoundsActions.cend());
}
return alist;
diff --git a/src/playback/internal/playbackuiactions.h b/src/playback/internal/playbackuiactions.h
index b07dc35042dbd..f68be84094a41 100644
--- a/src/playback/internal/playbackuiactions.h
+++ b/src/playback/internal/playbackuiactions.h
@@ -64,6 +64,7 @@ class PlaybackUiActions : public muse::ui::IUiActionsModule, public muse::async:
static const muse::ui::UiActionList s_loopBoundaryActions;
static const muse::ui::UiActionList s_diagnosticActions;
static const muse::ui::UiActionList s_onlineSoundsActions;
+ static const muse::ui::UiActionList s_mixerActions;
std::shared_ptr m_controller;
muse::async::Channel m_actionEnabledChanged;
diff --git a/src/playback/playbacktypes.h b/src/playback/playbacktypes.h
index f1e37dfa95b11..6c6d606f0f596 100644
--- a/src/playback/playbacktypes.h
+++ b/src/playback/playbacktypes.h
@@ -44,6 +44,7 @@ enum class MixerSectionType {
Volume,
Fader,
MuteAndSolo,
+ UnMuteAndUnSolo,
Title
};
@@ -57,6 +58,7 @@ inline QList allMixerSectionTypes()
MixerSectionType::Volume,
MixerSectionType::Fader,
MixerSectionType::MuteAndSolo,
+ MixerSectionType::UnMuteAndUnSolo,
MixerSectionType::Title
};
diff --git a/src/playback/qml/MuseScore/Playback/CMakeLists.txt b/src/playback/qml/MuseScore/Playback/CMakeLists.txt
index 279583f143e4d..1ca62395c88f1 100644
--- a/src/playback/qml/MuseScore/Playback/CMakeLists.txt
+++ b/src/playback/qml/MuseScore/Playback/CMakeLists.txt
@@ -74,6 +74,7 @@ qt_add_qml_module(playback_qml
internal/SoundFlag/ParamsGridView.qml
internal/VolumePressureMeter.qml
internal/VolumeSlider.qml
+ internal/MixerUnMuteAndUnSoloSection.qml
MixerPanel.qml
NotationRegionsBeingProcessedView.qml
OnlineSoundsStatusView.qml
diff --git a/src/playback/qml/MuseScore/Playback/MixerPanel.qml b/src/playback/qml/MuseScore/Playback/MixerPanel.qml
index 0cbe7bccad710..bff081dac9a19 100644
--- a/src/playback/qml/MuseScore/Playback/MixerPanel.qml
+++ b/src/playback/qml/MuseScore/Playback/MixerPanel.qml
@@ -305,21 +305,34 @@ ColumnLayout {
}
}
- MixerMuteAndSoloSection {
- id: muteAndSoloSection
+ Item {
+ width: contentColumn.width
+ height: muteAndSoloSection.height
- visible: contextMenuModel.muteAndSoloSectionVisible
- headerVisible: contextMenuModel.labelsSectionVisible
- headerWidth: prv.headerWidth
- channelItemWidth: prv.channelItemWidth
+ MixerMuteAndSoloSection {
+ id: muteAndSoloSection
- model: mixerPanelModel
+ visible: contextMenuModel.muteAndSoloSectionVisible
+ headerVisible: contextMenuModel.labelsSectionVisible
+ headerWidth: prv.headerWidth
+ channelItemWidth: prv.channelItemWidth
- navigationRowStart: 600
- needReadChannelName: prv.isPanelActivated
+ model: mixerPanelModel
+ navigationRowStart: 600
+ needReadChannelName: prv.isPanelActivated
- onNavigateControlIndexChanged: function(index) {
- prv.setNavigateControlIndex(index)
+ onNavigateControlIndexChanged: function(index) {
+ prv.setNavigateControlIndex(index)
+ }
+ }
+
+ MixerUnMuteAndUnSoloSection {
+ anchors.left: parent.left
+ anchors.verticalCenter: parent.verticalCenter
+ visible: contextMenuModel.unMuteAndUnSoloSectionVisible
+ headerVisible: contextMenuModel.labelsSectionVisible
+ headerWidth: prv.headerWidth
+ model: mixerPanelModel
}
}
diff --git a/src/playback/qml/MuseScore/Playback/internal/MixerUnMuteAndUnSoloSection.qml b/src/playback/qml/MuseScore/Playback/internal/MixerUnMuteAndUnSoloSection.qml
new file mode 100644
index 0000000000000..6d2e4791c4180
--- /dev/null
+++ b/src/playback/qml/MuseScore/Playback/internal/MixerUnMuteAndUnSoloSection.qml
@@ -0,0 +1,111 @@
+/*
+ * SPDX-License-Identifier: GPL-3.0-only
+ * MuseScore-Studio-CLA-applies
+ *
+ * MuseScore Studio
+ * Music Composition & Notation
+ *
+ * Copyright (C) 2021 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 .
+ */
+
+pragma ComponentBehavior: Bound
+
+import QtQuick
+
+import Muse.Ui
+import Muse.UiComponents
+import MuseScore.Playback
+
+Item {
+ id: root
+
+ property var model: undefined
+ property int headerWidth: 98
+ property bool headerVisible: true
+ property alias unMuteButton: unMuteAllButton
+ property alias unSoloButton: unSoloAllButton
+
+ height: 28
+ width: headerWidth
+ visible: headerVisible
+
+ Row {
+ anchors.centerIn: parent
+ spacing: 6
+
+ FlatToggleButton {
+ id: unMuteAllButton
+
+ height: 20
+ width: 20
+
+ icon: IconCode.MUTE
+
+ enabled: parent.enabled
+ visible: parent.visible
+
+ navigation.name: "UnMuteAllButton"
+ navigation.panel: root.channelItem.panel
+ navigation.row: root.navigationRowStart
+ navigation.accessible.name: root.accessibleName + " " + qsTrc("playback", "Unmute All")
+ navigation.onActiveChanged: {
+ if (navigation.active) {
+ root.navigateControlIndexChanged({row: navigation.row, column: navigation.column})
+ }
+ }
+
+ onToggled: {
+ for (let i = 0; i < model.rowCount(); i++) {
+ let item = model.get(i);
+
+ if(item.channelItem.type === MixerChannelItem.Metronome){
+ continue
+ }
+
+ item.channelItem.muted = false
+ }
+ }
+ }
+
+ FlatToggleButton {
+ id: unSoloAllButton
+
+ height: 20
+ width: 20
+
+ icon: IconCode.SOLO
+
+ enabled: parent.enabled
+ visible: parent.visible
+
+ navigation.name: "UnSoloAllButton"
+ navigation.panel: root.channelItem.panel
+ navigation.row: root.navigationRowStart + 1
+ navigation.accessible.name: root.accessibleName + " " + qsTrc("playback", "Unsolo All")
+ navigation.onActiveChanged: {
+ if (navigation.active) {
+ root.navigateControlIndexChanged({row: navigation.row, column: navigation.column})
+ }
+ }
+
+ onToggled: {
+ for (let i = 0; i < model.rowCount(); i++) {
+ let item = model.get(i);
+ item.channelItem.solo = false
+ }
+ }
+ }
+ }
+}
diff --git a/src/playback/qml/MuseScore/Playback/mixerpanelcontextmenumodel.cpp b/src/playback/qml/MuseScore/Playback/mixerpanelcontextmenumodel.cpp
index 0c5b11b107b7c..fe2ff0653620a 100644
--- a/src/playback/qml/MuseScore/Playback/mixerpanelcontextmenumodel.cpp
+++ b/src/playback/qml/MuseScore/Playback/mixerpanelcontextmenumodel.cpp
@@ -49,6 +49,7 @@ static TranslatableString mixerSectionTitle(MixerSectionType type)
case MixerSectionType::Fader: return TranslatableString("playback", "Fader");
case MixerSectionType::MuteAndSolo: return TranslatableString("playback", "Mute and solo");
case MixerSectionType::Title: return TranslatableString("playback", "Name");
+ case MixerSectionType::UnMuteAndUnSolo: return TranslatableString("playback", "Unmute and Unsolo");
case MixerSectionType::Unknown: break;
}
@@ -121,6 +122,11 @@ bool MixerPanelContextMenuModel::titleSectionVisible() const
return isSectionVisible(MixerSectionType::Title);
}
+bool MixerPanelContextMenuModel::unMuteAndUnSoloSectionVisible() const
+{
+ return isSectionVisible(MixerSectionType::UnMuteAndUnSolo);
+}
+
void MixerPanelContextMenuModel::load()
{
AbstractMenuModel::load();
@@ -149,6 +155,7 @@ void MixerPanelContextMenuModel::load()
buildSectionVisibleItem(MixerSectionType::Labels),
buildSectionVisibleItem(MixerSectionType::Sound),
buildSectionVisibleItem(MixerSectionType::AudioFX),
+ buildSectionVisibleItem(MixerSectionType::UnMuteAndUnSolo),
};
for (aux_channel_idx_t idx = 0; idx < AUX_CHANNEL_NUM; ++idx) {
@@ -318,6 +325,9 @@ void MixerPanelContextMenuModel::emitMixerSectionVisibilityChanged(MixerSectionT
case MixerSectionType::Title:
emit titleSectionVisibleChanged();
break;
+ case MixerSectionType::UnMuteAndUnSolo:
+ emit unMuteAndUnSoloSectionVisibleChanged();
+ break;
case MixerSectionType::Unknown:
break;
}
diff --git a/src/playback/qml/MuseScore/Playback/mixerpanelcontextmenumodel.h b/src/playback/qml/MuseScore/Playback/mixerpanelcontextmenumodel.h
index 34b18edce3e59..4b0e2a9a47edd 100644
--- a/src/playback/qml/MuseScore/Playback/mixerpanelcontextmenumodel.h
+++ b/src/playback/qml/MuseScore/Playback/mixerpanelcontextmenumodel.h
@@ -44,6 +44,7 @@ class MixerPanelContextMenuModel : public muse::uicomponents::AbstractMenuModel,
Q_PROPERTY(bool faderSectionVisible READ faderSectionVisible NOTIFY faderSectionVisibleChanged)
Q_PROPERTY(bool muteAndSoloSectionVisible READ muteAndSoloSectionVisible NOTIFY muteAndSoloSectionVisibleChanged)
Q_PROPERTY(bool titleSectionVisible READ titleSectionVisible NOTIFY titleSectionVisibleChanged)
+ Q_PROPERTY(bool unMuteAndUnSoloSectionVisible READ unMuteAndUnSoloSectionVisible NOTIFY unMuteAndUnSoloSectionVisibleChanged)
QML_ELEMENT
@@ -62,6 +63,7 @@ class MixerPanelContextMenuModel : public muse::uicomponents::AbstractMenuModel,
bool faderSectionVisible() const;
bool muteAndSoloSectionVisible() const;
bool titleSectionVisible() const;
+ bool unMuteAndUnSoloSectionVisible() const;
Q_INVOKABLE void load() override;
@@ -75,6 +77,7 @@ class MixerPanelContextMenuModel : public muse::uicomponents::AbstractMenuModel,
void faderSectionVisibleChanged();
void muteAndSoloSectionVisibleChanged();
void titleSectionVisibleChanged();
+ void unMuteAndUnSoloSectionVisibleChanged();
private:
bool isSectionVisible(MixerSectionType sectionType) const;
diff --git a/src/playback/qml/MuseScore/Playback/mixerpanelmodel.cpp b/src/playback/qml/MuseScore/Playback/mixerpanelmodel.cpp
index 721954da8ed6d..1ee2decb2ffe1 100644
--- a/src/playback/qml/MuseScore/Playback/mixerpanelmodel.cpp
+++ b/src/playback/qml/MuseScore/Playback/mixerpanelmodel.cpp
@@ -263,6 +263,20 @@ void MixerPanelModel::clear()
void MixerPanelModel::setupConnections()
{
+ currentProject()->masterNotation()->notation()->soloMuteState()->trackSoloMuteStateChanged().onReceive(
+ this, [this](const InstrumentTrackId& instrumentTrackId,
+ const notation::INotationSoloMuteState::SoloMuteState& newState) {
+ const IPlaybackController::InstrumentTrackIdMap& trackIdMap = controller()->instrumentTrackIdMap();
+ auto it = trackIdMap.find(instrumentTrackId);
+ if (it == trackIdMap.end()) {
+ return;
+ }
+
+ if (MixerChannelItem* item = findChannelItem(it->second)) {
+ item->loadSoloMuteState(newState);
+ }
+ });
+
audioSettings()->auxSoloMuteStateChanged().onReceive(
this, [this](const aux_channel_idx_t index,
notation::INotationSoloMuteState::SoloMuteState newSoloMuteState) {
diff --git a/tools/codestyle/tidy_file.sh b/tools/codestyle/tidy_file.sh
index 66ec22b7259d3..419559a3afee8 100755
--- a/tools/codestyle/tidy_file.sh
+++ b/tools/codestyle/tidy_file.sh
@@ -15,11 +15,13 @@ trap 'echo >&2 "$0: Error $?, line ${LINENO}, args: $*"; exit ${FAIL_FAST}' ERR
# the git index when multiple instances of this script are run in parallel.
HERE="${BASH_SOURCE%/*}" # path to dir that contains this script
+REPO_ROOT="${HERE}/../.."
+UNCRUSTIFY_CONFIG="${REPO_ROOT}/muse/tools/codestyle/uncrustify_muse.cfg" # lives in framework submodule
function uncrustify_file()
{
local file="$1" lang="$2" status
- uncrustify -c "${HERE}/uncrustify_musescore.cfg" --no-backup -l "${lang}" -f "${file}"
+ uncrustify -c "${UNCRUSTIFY_CONFIG}" --no-backup -l "${lang}" -f "${file}"
status=$?
rm -f "${file}.uncrustify" # remove possible temporary file
return ${status}