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}