LCOV - code coverage report
Current view: top level - src/playback/internal - playbackconfiguration.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 187 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : #include "playbackconfiguration.h"
      23              : 
      24              : #include "settings.h"
      25              : #include "types/string.h"
      26              : 
      27              : #include "playbacktypes.h"
      28              : 
      29              : #include "log.h"
      30              : 
      31              : using namespace mu;
      32              : using namespace mu::playback;
      33              : using namespace muse;
      34              : using namespace muse::audio;
      35              : 
      36              : static const std::string moduleName("playback");
      37              : 
      38              : static const Settings::Key PLAYBACK_CURSOR_TYPE_KEY(moduleName, "application/playback/cursorType");
      39              : static const Settings::Key PLAY_NOTES_WHEN_EDITING(moduleName, "score/note/playOnClick");
      40              : static const Settings::Key PLAY_NOTES_ON_MIDI_INPUT(moduleName, "score/note/playOnMidiInput");
      41              : static const Settings::Key PLAY_CHORD_WHEN_EDITING(moduleName, "score/chord/playOnAddNote");
      42              : static const Settings::Key PLAY_HARMONY_WHEN_EDITING(moduleName, "score/harmony/play/onedit");
      43              : 
      44              : static const Settings::Key SOUND_PRESETS_MULTI_SELECTION_KEY(moduleName, "application/playback/soundPresetsMultiSelectionEnabled");
      45              : 
      46              : static const Settings::Key MIXER_LABELS_SECTION_VISIBLE_KEY(moduleName, "playback/mixer/labelsSectionVisible");
      47              : static const Settings::Key MIXER_SOUND_SECTION_VISIBLE_KEY(moduleName, "playback/mixer/soundSectionVisible");
      48              : static const Settings::Key MIXER_AUDIO_FX_SECTION_VISIBLE_KEY(moduleName, "playback/mixer/audioFxSectionVisible");
      49              : static const Settings::Key MIXER_BALANCE_SECTION_VISIBLE_KEY(moduleName, "playback/mixer/balanceSectionVisible");
      50              : static const Settings::Key MIXER_VOLUME_SECTION_VISIBLE_KEY(moduleName, "playback/mixer/volumeSectionVisible");
      51              : static const Settings::Key MIXER_FADER_SECTION_VISIBLE_KEY(moduleName, "playback/mixer/faderSectionVisible");
      52              : static const Settings::Key MIXER_MUTE_AND_SOLO_SECTION_VISIBLE_KEY(moduleName, "playback/mixer/muteAndSoloSectionVisible");
      53              : static const Settings::Key MIXER_TITLE_SECTION_VISIBLE_KEY(moduleName, "playback/mixer/titleSectionVisible");
      54              : 
      55              : static const Settings::Key MIXER_RESET_SOUND_FLAGS_WHEN_CHANGE_SOUND_WARNING(moduleName,
      56              :                                                                              "playback/mixer/needToShowAboutResetSoundFlagsWhwnChangeSoundWarning");
      57              : static const Settings::Key MIXER_RESET_SOUND_FLAGS_WHEN_CHANGE_PLAYBACK_PROFILE_WARNING(moduleName,
      58              :                                                                                         "playback/mixer/needToShowAboutResetSoundFlagsWhwnChangePlaybackProfileWarning");
      59              : 
      60              : static const Settings::Key ONLINE_SOUNDS_SHOW_ERROR(moduleName, "playback/onlineSounds/showError");
      61              : static const Settings::Key ONLINE_SOUNDS_SHOW_PROGRESS_BAR_MODE(moduleName, "playback/onlineSounds/showProgressBarMode");
      62              : 
      63              : static const Settings::Key MUTE_HIDDEN_INSTRUMENTS(moduleName, "playback/mixer/muteHiddenInstruments");
      64              : 
      65              : static const Settings::Key DEFAULT_SOUND_PROFILE_FOR_NEW_PROJECTS(moduleName, "playback/profiles/defaultProfileName");
      66              : static const SoundProfileName BASIC_PROFILE_NAME(u"MuseScore Basic");
      67              : static const SoundProfileName MUSESOUNDS_PROFILE_NAME(u"MuseSounds");
      68              : static const SoundProfileName COMPAT_MUSESOUNDS_PROFILE_NAME(u"Muse Sounds");
      69              : 
      70            0 : static Settings::Key mixerSectionVisibleKey(MixerSectionType sectionType)
      71              : {
      72            0 :     switch (sectionType) {
      73            0 :     case MixerSectionType::Labels: return MIXER_LABELS_SECTION_VISIBLE_KEY;
      74            0 :     case MixerSectionType::Sound: return MIXER_SOUND_SECTION_VISIBLE_KEY;
      75            0 :     case MixerSectionType::AudioFX: return MIXER_AUDIO_FX_SECTION_VISIBLE_KEY;
      76            0 :     case MixerSectionType::Balance: return MIXER_BALANCE_SECTION_VISIBLE_KEY;
      77            0 :     case MixerSectionType::Volume: return MIXER_VOLUME_SECTION_VISIBLE_KEY;
      78            0 :     case MixerSectionType::Fader: return MIXER_FADER_SECTION_VISIBLE_KEY;
      79            0 :     case MixerSectionType::MuteAndSolo: return MIXER_MUTE_AND_SOLO_SECTION_VISIBLE_KEY;
      80            0 :     case MixerSectionType::Title: return MIXER_TITLE_SECTION_VISIBLE_KEY;
      81            0 :     case MixerSectionType::Unknown: break;
      82              :     }
      83              : 
      84            0 :     return Settings::Key();
      85              : }
      86              : 
      87            0 : static Settings::Key auxSendVisibleKey(aux_channel_idx_t index)
      88              : {
      89            0 :     return Settings::Key(moduleName, "playback/mixer/auxSend" + std::to_string(index) + "Visible");
      90              : }
      91              : 
      92            0 : static Settings::Key auxChannelVisibleKey(aux_channel_idx_t index)
      93              : {
      94            0 :     return Settings::Key(moduleName, "playback/mixer/auxChannel" + std::to_string(index) + "Visible");
      95              : }
      96              : 
      97            0 : void PlaybackConfiguration::init()
      98              : {
      99            0 :     settings()->setDefaultValue(PLAY_NOTES_WHEN_EDITING, Val(true));
     100            0 :     settings()->valueChanged(PLAY_NOTES_WHEN_EDITING).onReceive(this, [this](const Val&) {
     101            0 :         m_playNotesWhenEditingChanged.notify();
     102            0 :     });
     103            0 :     settings()->setDefaultValue(PLAY_CHORD_WHEN_EDITING, Val(true));
     104            0 :     settings()->valueChanged(PLAY_CHORD_WHEN_EDITING).onReceive(this, [this](const Val& val) {
     105            0 :         m_playChordWhenEditingChanged.send(val.toBool());
     106            0 :     });
     107            0 :     settings()->setDefaultValue(PLAY_HARMONY_WHEN_EDITING, Val(true));
     108            0 :     settings()->valueChanged(PLAY_HARMONY_WHEN_EDITING).onReceive(this, [this](const Val& val) {
     109            0 :         m_playHarmonyWhenEditingChanged.send(val.toBool());
     110            0 :     });
     111            0 :     settings()->setDefaultValue(PLAY_NOTES_ON_MIDI_INPUT, Val(true));
     112            0 :     settings()->valueChanged(PLAY_NOTES_ON_MIDI_INPUT).onReceive(this, [this](const Val& val) {
     113            0 :         m_playNotesOnMidiInputChanged.send(val.toBool());
     114            0 :     });
     115            0 :     settings()->setDefaultValue(PLAYBACK_CURSOR_TYPE_KEY, Val(PlaybackCursorType::STEPPED));
     116            0 :     settings()->setDefaultValue(SOUND_PRESETS_MULTI_SELECTION_KEY, Val(false));
     117            0 :     settings()->setDefaultValue(MIXER_RESET_SOUND_FLAGS_WHEN_CHANGE_SOUND_WARNING, Val(true));
     118            0 :     settings()->setDefaultValue(MIXER_RESET_SOUND_FLAGS_WHEN_CHANGE_PLAYBACK_PROFILE_WARNING, Val(true));
     119              : 
     120            0 :     for (MixerSectionType sectionType : allMixerSectionTypes()) {
     121            0 :         bool sectionEnabledByDefault = sectionType != MixerSectionType::Volume;
     122            0 :         settings()->setDefaultValue(mixerSectionVisibleKey(sectionType), Val(sectionEnabledByDefault));
     123            0 :         settings()->valueChanged(mixerSectionVisibleKey(sectionType)).onReceive(this, [this, sectionType](const Val& val) {
     124            0 :             m_isMixerSectionVisibleChanged.send(sectionType, val.toBool());
     125            0 :         });
     126            0 :     }
     127              : 
     128            0 :     settings()->setDefaultValue(MUTE_HIDDEN_INSTRUMENTS, Val(true));
     129            0 :     settings()->valueChanged(MUTE_HIDDEN_INSTRUMENTS).onReceive(nullptr, [this](const Val& mute) {
     130            0 :         m_muteHiddenInstrumentsChanged.send(mute.toBool());
     131            0 :     });
     132              : 
     133            0 :     settings()->setDefaultValue(DEFAULT_SOUND_PROFILE_FOR_NEW_PROJECTS, Val(fallbackSoundProfileStr().toStdString()));
     134              : 
     135            0 :     for (aux_channel_idx_t idx = 0; idx < AUX_CHANNEL_NUM; ++idx) {
     136            0 :         Settings::Key auxSendKey = auxSendVisibleKey(idx);
     137            0 :         Settings::Key auxChannelKey = auxChannelVisibleKey(idx);
     138              : 
     139            0 :         settings()->setDefaultValue(auxSendKey, Val(idx == REVERB_CHANNEL_IDX));
     140            0 :         settings()->setDefaultValue(auxChannelKey, Val(false));
     141              : 
     142            0 :         settings()->valueChanged(auxSendKey).onReceive(this, [this, idx](const Val& val) {
     143            0 :             m_isAuxSendVisibleChanged.send(idx, val.toBool());
     144            0 :         });
     145              : 
     146            0 :         settings()->valueChanged(auxChannelKey).onReceive(this, [this, idx](const Val& val) {
     147            0 :             m_isAuxChannelVisibleChanged.send(idx, val.toBool());
     148            0 :         });
     149            0 :     }
     150              : 
     151            0 :     settings()->setDefaultValue(ONLINE_SOUNDS_SHOW_ERROR, Val(true));
     152            0 :     settings()->valueChanged(ONLINE_SOUNDS_SHOW_ERROR).onReceive(nullptr, [this](const Val&) {
     153            0 :         m_shouldShowOnlineSoundsProcessingErrorChanged.notify();
     154            0 :     });
     155              : 
     156            0 :     settings()->setDefaultValue(ONLINE_SOUNDS_SHOW_PROGRESS_BAR_MODE, Val(static_cast<int>(OnlineSoundsShowProgressBarMode::Always)));
     157            0 :     settings()->valueChanged(ONLINE_SOUNDS_SHOW_PROGRESS_BAR_MODE).onReceive(nullptr, [this](const Val&) {
     158            0 :         m_onlineSoundsShowProgressBarModeChanged.notify();
     159            0 :     });
     160            0 : }
     161              : 
     162            0 : bool PlaybackConfiguration::playNotesWhenEditing() const
     163              : {
     164            0 :     return settings()->value(PLAY_NOTES_WHEN_EDITING).toBool();
     165              : }
     166              : 
     167            0 : void PlaybackConfiguration::setPlayNotesWhenEditing(bool value)
     168              : {
     169            0 :     settings()->setSharedValue(PLAY_NOTES_WHEN_EDITING, Val(value));
     170            0 : }
     171              : 
     172            0 : muse::async::Notification PlaybackConfiguration::playNotesWhenEditingChanged() const
     173              : {
     174            0 :     return m_playNotesWhenEditingChanged;
     175              : }
     176              : 
     177            0 : bool PlaybackConfiguration::playChordWhenEditing() const
     178              : {
     179            0 :     return settings()->value(PLAY_CHORD_WHEN_EDITING).toBool();
     180              : }
     181              : 
     182            0 : void PlaybackConfiguration::setPlayChordWhenEditing(bool value)
     183              : {
     184            0 :     settings()->setSharedValue(PLAY_CHORD_WHEN_EDITING, Val(value));
     185            0 : }
     186              : 
     187            0 : async::Channel<bool> PlaybackConfiguration::playChordWhenEditingChanged() const
     188              : {
     189            0 :     return m_playChordWhenEditingChanged;
     190              : }
     191              : 
     192            0 : bool PlaybackConfiguration::playHarmonyWhenEditing() const
     193              : {
     194            0 :     return settings()->value(PLAY_HARMONY_WHEN_EDITING).toBool();
     195              : }
     196              : 
     197            0 : void PlaybackConfiguration::setPlayHarmonyWhenEditing(bool value)
     198              : {
     199            0 :     settings()->setSharedValue(PLAY_HARMONY_WHEN_EDITING, Val(value));
     200            0 : }
     201              : 
     202            0 : async::Channel<bool> PlaybackConfiguration::playHarmonyWhenEditingChanged() const
     203              : {
     204            0 :     return m_playHarmonyWhenEditingChanged;
     205              : }
     206              : 
     207            0 : bool PlaybackConfiguration::playNotesOnMidiInput() const
     208              : {
     209            0 :     return settings()->value(PLAY_NOTES_ON_MIDI_INPUT).toBool();
     210              : }
     211              : 
     212            0 : void PlaybackConfiguration::setPlayNotesOnMidiInput(bool value)
     213              : {
     214            0 :     settings()->setSharedValue(PLAY_NOTES_ON_MIDI_INPUT, Val(value));
     215            0 : }
     216              : 
     217            0 : muse::async::Channel<bool> PlaybackConfiguration::playNotesOnMidiInputChanged() const
     218              : {
     219            0 :     return m_playNotesOnMidiInputChanged;
     220              : }
     221              : 
     222            0 : PlaybackCursorType PlaybackConfiguration::cursorType() const
     223              : {
     224            0 :     return settings()->value(PLAYBACK_CURSOR_TYPE_KEY).toEnum<PlaybackCursorType>();
     225              : }
     226              : 
     227            0 : bool PlaybackConfiguration::isMixerSectionVisible(MixerSectionType sectionType) const
     228              : {
     229            0 :     return settings()->value(mixerSectionVisibleKey(sectionType)).toBool();
     230              : }
     231              : 
     232            0 : void PlaybackConfiguration::setMixerSectionVisible(MixerSectionType sectionType, bool visible)
     233              : {
     234            0 :     settings()->setSharedValue(mixerSectionVisibleKey(sectionType), Val(visible));
     235            0 : }
     236              : 
     237            0 : muse::async::Channel<MixerSectionType, bool> PlaybackConfiguration::isMixerSectionVisibleChanged() const
     238              : {
     239            0 :     return m_isMixerSectionVisibleChanged;
     240              : }
     241              : 
     242            0 : bool PlaybackConfiguration::isAuxSendVisible(aux_channel_idx_t index) const
     243              : {
     244            0 :     return settings()->value(auxSendVisibleKey(index)).toBool();
     245              : }
     246              : 
     247            0 : void PlaybackConfiguration::setAuxSendVisible(aux_channel_idx_t index, bool visible)
     248              : {
     249            0 :     settings()->setSharedValue(auxSendVisibleKey(index), Val(visible));
     250            0 : }
     251              : 
     252            0 : muse::async::Channel<aux_channel_idx_t, bool> PlaybackConfiguration::isAuxSendVisibleChanged() const
     253              : {
     254            0 :     return m_isAuxSendVisibleChanged;
     255              : }
     256              : 
     257            0 : bool PlaybackConfiguration::isAuxChannelVisible(aux_channel_idx_t index) const
     258              : {
     259            0 :     return settings()->value(auxChannelVisibleKey(index)).toBool();
     260              : }
     261              : 
     262            0 : void PlaybackConfiguration::setAuxChannelVisible(aux_channel_idx_t index, bool visible) const
     263              : {
     264            0 :     settings()->setSharedValue(auxChannelVisibleKey(index), Val(visible));
     265            0 : }
     266              : 
     267            0 : muse::async::Channel<aux_channel_idx_t, bool> PlaybackConfiguration::isAuxChannelVisibleChanged() const
     268              : {
     269            0 :     return m_isAuxChannelVisibleChanged;
     270              : }
     271              : 
     272            0 : gain_t PlaybackConfiguration::defaultAuxSendValue(aux_channel_idx_t index, AudioSourceType sourceType,
     273              :                                                   const muse::String& instrumentSoundId) const
     274              : {
     275            0 :     TRACEFUNC;
     276              : 
     277            0 :     constexpr gain_t DEFAULT_VALUE = 0.30f;
     278              : 
     279            0 :     if (sourceType == AudioSourceType::MuseSampler) {
     280            0 :         if (index == REVERB_CHANNEL_IDX) {
     281            0 :             float lvl = musesamplerInfo()->defaultReverbLevel(instrumentSoundId);
     282            0 :             return muse::RealIsNull(lvl) ? DEFAULT_VALUE : lvl;
     283              :         }
     284            0 :     } else if (sourceType == AudioSourceType::Vsti) {
     285            0 :         return 0.f;
     286              :     }
     287              : 
     288            0 :     return DEFAULT_VALUE;
     289            0 : }
     290              : 
     291            0 : bool PlaybackConfiguration::muteHiddenInstruments() const
     292              : {
     293            0 :     return settings()->value(MUTE_HIDDEN_INSTRUMENTS).toBool();
     294              : }
     295              : 
     296            0 : void PlaybackConfiguration::setMuteHiddenInstruments(bool mute)
     297              : {
     298            0 :     settings()->setSharedValue(MUTE_HIDDEN_INSTRUMENTS, Val(mute));
     299            0 : }
     300              : 
     301            0 : muse::async::Channel<bool> PlaybackConfiguration::muteHiddenInstrumentsChanged() const
     302              : {
     303            0 :     return m_muteHiddenInstrumentsChanged;
     304              : }
     305              : 
     306            0 : const SoundProfileName& PlaybackConfiguration::basicSoundProfileName() const
     307              : {
     308            0 :     return BASIC_PROFILE_NAME;
     309              : }
     310              : 
     311            0 : const SoundProfileName& PlaybackConfiguration::museSoundsProfileName() const
     312              : {
     313            0 :     return MUSESOUNDS_PROFILE_NAME;
     314              : }
     315              : 
     316            0 : const SoundProfileName& PlaybackConfiguration::compatMuseSoundsProfileName() const
     317              : {
     318            0 :     return COMPAT_MUSESOUNDS_PROFILE_NAME;
     319              : }
     320              : 
     321            0 : SoundProfileName PlaybackConfiguration::defaultProfileForNewProjects() const
     322              : {
     323            0 :     return muse::String::fromStdString(settings()->value(DEFAULT_SOUND_PROFILE_FOR_NEW_PROJECTS).toString());
     324              : }
     325              : 
     326            0 : void PlaybackConfiguration::setDefaultProfileForNewProjects(const SoundProfileName& name)
     327              : {
     328            0 :     settings()->setSharedValue(DEFAULT_SOUND_PROFILE_FOR_NEW_PROJECTS, Val(name.toStdString()));
     329            0 : }
     330              : 
     331            0 : bool PlaybackConfiguration::soundPresetsMultiSelectionEnabled() const
     332              : {
     333            0 :     return settings()->value(SOUND_PRESETS_MULTI_SELECTION_KEY).toBool();
     334              : }
     335              : 
     336            0 : void PlaybackConfiguration::setSoundPresetsMultiSelectionEnabled(bool enabled)
     337              : {
     338            0 :     settings()->setSharedValue(SOUND_PRESETS_MULTI_SELECTION_KEY, Val(enabled));
     339            0 : }
     340              : 
     341            0 : bool PlaybackConfiguration::needToShowResetSoundFlagsWhenChangeSoundWarning() const
     342              : {
     343            0 :     return settings()->value(MIXER_RESET_SOUND_FLAGS_WHEN_CHANGE_SOUND_WARNING).toBool();
     344              : }
     345              : 
     346            0 : void PlaybackConfiguration::setNeedToShowResetSoundFlagsWhenChangeSoundWarning(bool show)
     347              : {
     348            0 :     settings()->setSharedValue(MIXER_RESET_SOUND_FLAGS_WHEN_CHANGE_SOUND_WARNING, Val(show));
     349            0 : }
     350              : 
     351            0 : bool PlaybackConfiguration::needToShowResetSoundFlagsWhenChangePlaybackProfileWarning() const
     352              : {
     353            0 :     return settings()->value(MIXER_RESET_SOUND_FLAGS_WHEN_CHANGE_PLAYBACK_PROFILE_WARNING).toBool();
     354              : }
     355              : 
     356            0 : void PlaybackConfiguration::setNeedToShowResetSoundFlagsWhenChangePlaybackProfileWarning(bool show)
     357              : {
     358            0 :     settings()->setSharedValue(MIXER_RESET_SOUND_FLAGS_WHEN_CHANGE_PLAYBACK_PROFILE_WARNING, Val(show));
     359            0 : }
     360              : 
     361            0 : bool PlaybackConfiguration::shouldShowOnlineSoundsProcessingError() const
     362              : {
     363            0 :     return settings()->value(ONLINE_SOUNDS_SHOW_ERROR).toBool();
     364              : }
     365              : 
     366            0 : void PlaybackConfiguration::setShouldShowOnlineSoundsProcessingError(bool show)
     367              : {
     368            0 :     settings()->setSharedValue(ONLINE_SOUNDS_SHOW_ERROR, Val(show));
     369            0 : }
     370              : 
     371            0 : muse::async::Notification PlaybackConfiguration::shouldShowOnlineSoundsProcessingErrorChanged() const
     372              : {
     373            0 :     return m_shouldShowOnlineSoundsProcessingErrorChanged;
     374              : }
     375              : 
     376            0 : muse::String PlaybackConfiguration::onlineSoundsHandbookUrl() const
     377              : {
     378            0 :     return u"https://handbook.musescore.org/sound-and-playback/installing-muse-sounds/online-sounds";
     379              : }
     380              : 
     381            0 : OnlineSoundsShowProgressBarMode PlaybackConfiguration::onlineSoundsShowProgressBarMode() const
     382              : {
     383            0 :     return static_cast<OnlineSoundsShowProgressBarMode>(settings()->value(ONLINE_SOUNDS_SHOW_PROGRESS_BAR_MODE).toInt());
     384              : }
     385              : 
     386            0 : void PlaybackConfiguration::setOnlineSoundsShowProgressBarMode(OnlineSoundsShowProgressBarMode mode)
     387              : {
     388            0 :     settings()->setSharedValue(ONLINE_SOUNDS_SHOW_PROGRESS_BAR_MODE, Val(static_cast<int>(mode)));
     389            0 : }
     390              : 
     391            0 : muse::async::Notification PlaybackConfiguration::onlineSoundsShowProgressBarModeChanged() const
     392              : {
     393            0 :     return m_onlineSoundsShowProgressBarModeChanged;
     394              : }
     395              : 
     396            0 : bool PlaybackConfiguration::shouldMeasureInputLag() const
     397              : {
     398            0 :     return audioConfiguration()->shouldMeasureInputLag();
     399              : }
     400              : 
     401            0 : const SoundProfileName& PlaybackConfiguration::fallbackSoundProfileStr() const
     402              : {
     403            0 :     if (musesamplerInfo() && musesamplerInfo()->isLoaded()) {
     404            0 :         return MUSESOUNDS_PROFILE_NAME;
     405              :     }
     406              : 
     407            0 :     return BASIC_PROFILE_NAME;
     408              : }
        

Generated by: LCOV version 2.0-1