LCOV - code coverage report
Current view: top level - src/playback/internal - playbackcommandsstate.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 130 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) 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              : 
      23              : #include "playbackcommandsstate.h"
      24              : 
      25              : #include "notation/inotation.h"
      26              : #include "notation/inotationinteraction.h"
      27              : 
      28              : #include "../playbackcommands.h"
      29              : 
      30              : using namespace muse;
      31              : using namespace muse::rcommand;
      32              : using namespace mu::playback;
      33              : using namespace mu::notation;
      34              : 
      35              : static const muse::Uri PROJECT_PAGE_URI("musescore://notation");
      36              : 
      37            0 : std::string PlaybackCommandsState::moduleName() const
      38              : {
      39            0 :     return "playback";
      40              : }
      41              : 
      42            0 : void PlaybackCommandsState::init()
      43              : {
      44            0 :     projectSession()->projectChanged().onNotify(this, [this]() {
      45            0 :         updateCommandStates();
      46            0 :     });
      47              : 
      48            0 :     projectSession()->currentNotationChanged().onNotify(this, [this]() {
      49            0 :         const INotationPtr currNotation = projectSession()->currentNotation();
      50            0 :         if (!currNotation) {
      51            0 :             return;
      52              :         }
      53              : 
      54            0 :         const INotationInteractionPtr interaction = currNotation->interaction();
      55            0 :         interaction->selectionChanged().onNotify(this, [this]() {
      56            0 :             updateCommandStates({ PLAY_SELECTION_COMMAND });
      57            0 :         }, Asyncable::Mode::SetReplace);
      58              : 
      59            0 :         interaction->isEditingElementChanged().onNotify(this, [this]() {
      60            0 :             updateCommandStates({ PLAY_SELECTION_COMMAND });
      61            0 :         }, Asyncable::Mode::SetReplace);
      62            0 :     });
      63              : 
      64            0 :     if (interactive()) {
      65            0 :         interactive()->opened().onReceive(this, [this](const muse::Uri&) {
      66            0 :             updateCommandStates();
      67            0 :         });
      68              :     }
      69              : 
      70            0 :     playbackController()->isPlayAllowedChanged().onReceive(this, [this](bool) {
      71            0 :         updateCommandStates();
      72            0 :     });
      73              : 
      74            0 :     playbackController()->isPlayingChanged().onReceive(this, [this](bool) {
      75            0 :         updateCommandStates();
      76            0 :     });
      77              : 
      78            0 :     playbackController()->loopEnabledChanged().onReceive(this, [this](bool) {
      79            0 :         updateCommandStates({ LOOP_TOGGLE_COMMAND });
      80            0 :     });
      81              : 
      82            0 :     playbackController()->onlineSoundsChanged().onNotify(this, [this]() {
      83            0 :         updateCommandStates({ CLEAR_ONLINESOUNDS_CACHE_COMMAND });
      84            0 :     });
      85              : 
      86            0 :     notationConfiguration()->isMetronomeEnabledChanged().onNotify(this, [this]() {
      87            0 :         updateCommandStates({ METRONOME_TOGGLE_COMMAND });
      88            0 :     });
      89              : 
      90            0 :     notationConfiguration()->isMidiInputEnabledChanged().onNotify(this, [this]() {
      91            0 :         updateCommandStates({ MIDI_TOGGLE_COMMAND });
      92            0 :     });
      93              : 
      94            0 :     notationConfiguration()->midiUseWrittenPitch().ch.onReceive(this, [this](bool) {
      95            0 :         updateCommandStates({ MIDI_INPUT_WRITTEN_PITCH_COMMAND, MIDI_INPUT_SOUNDING_PITCH_COMMAND });
      96            0 :     });
      97              : 
      98            0 :     notationConfiguration()->isPlayRepeatsChanged().onNotify(this, [this]() {
      99            0 :         updateCommandStates({ REPEATS_TOGGLE_COMMAND });
     100            0 :     });
     101              : 
     102            0 :     notationConfiguration()->isPlayChordSymbolsChanged().onNotify(this, [this]() {
     103            0 :         updateCommandStates({ CHORDSYMBOLS_TOGGLE_COMMAND });
     104            0 :     });
     105              : 
     106            0 :     notationConfiguration()->isAutomaticallyPanEnabledChanged().onNotify(this, [this]() {
     107            0 :         updateCommandStates({ PAN_TOGGLE_COMMAND });
     108            0 :     });
     109              : 
     110            0 :     notationConfiguration()->isCountInEnabledChanged().onNotify(this, [this]() {
     111            0 :         updateCommandStates({ COUNTIN_TOGGLE_COMMAND });
     112            0 :     });
     113              : 
     114            0 :     playbackConfiguration()->playNotesWhenEditingChanged().onNotify(this, [this]() {
     115            0 :         updateCommandStates({ HEAR_PLAYBACK_WHEN_EDITING_TOGGLE_COMMAND });
     116            0 :     });
     117              : 
     118            0 :     m_moduleRegister = commandsRegister()->moduleRegister(moduleName());
     119            0 :     IF_ASSERT_FAILED(m_moduleRegister) {
     120            0 :         return;
     121              :     }
     122              : 
     123            0 :     updateCommandStates();
     124              : }
     125              : 
     126            0 : void PlaybackCommandsState::deinit()
     127              : {
     128            0 :     projectSession()->projectChanged().disconnect(this);
     129            0 :     projectSession()->currentNotationChanged().disconnect(this);
     130            0 :     if (interactive()) {
     131            0 :         interactive()->opened().disconnect(this);
     132              :     }
     133            0 :     playbackController()->isPlayAllowedChanged().disconnect(this);
     134            0 :     playbackController()->isPlayingChanged().disconnect(this);
     135            0 :     playbackController()->loopEnabledChanged().disconnect(this);
     136            0 :     playbackController()->onlineSoundsChanged().disconnect(this);
     137            0 :     playbackConfiguration()->playNotesWhenEditingChanged().disconnect(this);
     138            0 :     notationConfiguration()->isMetronomeEnabledChanged().disconnect(this);
     139            0 :     notationConfiguration()->isMidiInputEnabledChanged().disconnect(this);
     140            0 :     notationConfiguration()->midiUseWrittenPitch().ch.disconnect(this);
     141            0 :     notationConfiguration()->isPlayRepeatsChanged().disconnect(this);
     142            0 :     notationConfiguration()->isPlayChordSymbolsChanged().disconnect(this);
     143            0 :     notationConfiguration()->isAutomaticallyPanEnabledChanged().disconnect(this);
     144            0 :     notationConfiguration()->isCountInEnabledChanged().disconnect(this);
     145            0 : }
     146              : 
     147            0 : void PlaybackCommandsState::updateCommandStates(const std::vector<Command>& commands)
     148              : {
     149            0 :     IF_ASSERT_FAILED(m_moduleRegister) {
     150            0 :         return;
     151              :     }
     152              : 
     153            0 :     const auto& commandList = commands.empty() ? m_moduleRegister->commandList() : commands;
     154              : 
     155            0 :     for (const auto& command : commandList) {
     156            0 :         CommandState newState = commandState(command);
     157            0 :         if (m_commandStates[command] != newState) {
     158            0 :             m_commandStates[command] = newState;
     159            0 :             m_commandStateChanged.send(command, newState);
     160              :         }
     161              :     }
     162              : }
     163              : 
     164            0 : CommandState PlaybackCommandsState::commandState(const Command& command) const
     165              : {
     166            0 :     if (!isProjectOpened()) {
     167            0 :         return CommandState(false, false);
     168              :     }
     169              : 
     170            0 :     if (!playbackController()->isPlayAllowed()) {
     171            0 :         return CommandState(false, false);
     172              :     }
     173              : 
     174            0 :     if (command == PLAY_COMMAND) {
     175            0 :         return CommandState(true, playbackController()->isPlaying());
     176            0 :     } else if (command == PLAY_SELECTION_COMMAND) {
     177            0 :         const INotationPtr currNotation = projectSession()->currentNotation();
     178            0 :         const INotationInteractionPtr interaction = currNotation ? currNotation->interaction() : nullptr;
     179            0 :         bool enabled = interaction && !interaction->isEditingElement();
     180            0 :         return CommandState(enabled, false);
     181            0 :     } else if (command == LOOP_TOGGLE_COMMAND) {
     182            0 :         return CommandState(true, playbackController()->isLoopEnabled());
     183            0 :     } else if (command == METRONOME_TOGGLE_COMMAND) {
     184            0 :         return CommandState(true, notationConfiguration()->isMetronomeEnabled());
     185            0 :     } else if (command == MIDI_TOGGLE_COMMAND) {
     186            0 :         return CommandState(true, notationConfiguration()->isMidiInputEnabled());
     187            0 :     } else if (command == MIDI_INPUT_WRITTEN_PITCH_COMMAND) {
     188            0 :         return CommandState(true, notationConfiguration()->midiUseWrittenPitch().val);
     189            0 :     } else if (command == MIDI_INPUT_SOUNDING_PITCH_COMMAND) {
     190            0 :         return CommandState(true, !notationConfiguration()->midiUseWrittenPitch().val);
     191            0 :     } else if (command == REPEATS_TOGGLE_COMMAND) {
     192            0 :         return CommandState(true, notationConfiguration()->isPlayRepeatsEnabled());
     193            0 :     } else if (command == CHORDSYMBOLS_TOGGLE_COMMAND) {
     194            0 :         return CommandState(true, notationConfiguration()->isPlayChordSymbolsEnabled());
     195            0 :     } else if (command == HEAR_PLAYBACK_WHEN_EDITING_TOGGLE_COMMAND) {
     196            0 :         return CommandState(true, playbackConfiguration()->playNotesWhenEditing());
     197            0 :     } else if (command == PAN_TOGGLE_COMMAND) {
     198            0 :         return CommandState(true, notationConfiguration()->isAutomaticallyPanEnabled());
     199            0 :     } else if (command == COUNTIN_TOGGLE_COMMAND) {
     200            0 :         return CommandState(true, notationConfiguration()->isCountInEnabled());
     201            0 :     } else if (command == CLEAR_ONLINESOUNDS_CACHE_COMMAND) {
     202            0 :         return CommandState(true, !playbackController()->onlineSounds().empty());
     203              :     }
     204              : 
     205            0 :     return CommandState(true, false);
     206              : }
     207              : 
     208            0 : async::Channel<Command, CommandState> PlaybackCommandsState::commandStateChanged() const
     209              : {
     210            0 :     return m_commandStateChanged;
     211              : }
     212              : 
     213            0 : bool PlaybackCommandsState::isProjectOpened() const
     214              : {
     215            0 :     if (!projectSession()->project()) {
     216            0 :         return false;
     217              :     }
     218              : 
     219            0 :     return true;
     220              : }
        

Generated by: LCOV version 2.0-1