LCOV - code coverage report
Current view: top level - src/playback/internal - playbackcontroller.h Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 2 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) 2025 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              : #pragma once
      24              : 
      25              : #include <optional>
      26              : #include <unordered_map>
      27              : 
      28              : #include "modularity/ioc.h"
      29              : #include "async/asyncable.h"
      30              : #include "project/iprojectsession.h"
      31              : #include "engraving/types/types.h"
      32              : #include "notation/inotationautomation.h"
      33              : #include "notation/inotationconfiguration.h"
      34              : #include "notation/inotationplayback.h"
      35              : #include "project/iprojectaudiosettings.h"
      36              : #include "audio/main/iplayer.h"
      37              : #include "audio/main/iplayback.h"
      38              : #include "audio/common/audiotypes.h"
      39              : #include "tours/itoursservice.h"
      40              : #include "interactive/iinteractive.h"
      41              : 
      42              : #include "drumsetloader.h"
      43              : 
      44              : #include "../iplaybackcontroller.h"
      45              : #include "../iplaybackconfiguration.h"
      46              : #include "../isoundprofilesrepository.h"
      47              : 
      48              : namespace mu::playback {
      49              : class OnlineSoundsController;
      50              : class PlaybackController : public IPlaybackController, public muse::async::Asyncable, public muse::Contextable
      51              : {
      52              :     muse::GlobalInject<IPlaybackConfiguration> configuration;
      53              :     muse::GlobalInject<notation::INotationConfiguration> notationConfiguration;
      54              :     muse::ContextInject<ISoundProfilesRepository> profilesRepo = { this };
      55              :     muse::ContextInject<muse::audio::IPlayback> playback = { this };
      56              :     muse::ContextInject<project::IProjectSession> projectSession = { this };
      57              :     muse::ContextInject<muse::tours::IToursService> tours = { this };
      58              :     muse::ContextInject<muse::IInteractive> interactive = { this };
      59              : 
      60              : public:
      61              :     PlaybackController(const muse::modularity::ContextPtr& iocCtx);
      62              :     ~PlaybackController() override;
      63              : 
      64              :     void init();
      65              :     void deinit();
      66              : 
      67              :     // IPlaybackState
      68              :     bool isPlaying() const override;
      69              :     muse::async::Channel<bool> isPlayingChanged() const override;
      70              : 
      71              :     muse::audio::secs_t playbackPosition() const override;
      72              :     muse::async::Channel<muse::audio::secs_t> playbackPositionChanged() const override;
      73              :     // --------------
      74              : 
      75              :     // IPlaybackController
      76              :     bool isPlaybackInited() const override;
      77              :     muse::async::Channel<bool> playbackInitedChanged() const override;
      78              : 
      79              :     bool isPlayAllowed() const override;
      80              :     muse::async::Channel<bool> isPlayAllowedChanged() const override;
      81              : 
      82              :     muse::Ret togglePlay() override;
      83              :     muse::Ret play(bool showErrors = true) override;
      84              :     muse::Ret playFromSelection(bool showErrors = true) override;
      85              :     muse::Ret pause(bool select = false) override;
      86              :     muse::Ret stop() override;
      87              :     muse::Ret rewind(muse::secs_t secs) override;
      88              : 
      89              :     bool isLoopEnabled() const override;
      90              :     muse::async::Channel<bool> loopEnabledChanged() const override;
      91              :     muse::Ret toggleLoopPlayback() override;
      92              :     muse::Ret addLoopBoundary(LoopBoundaryType type) override;
      93              : 
      94              :     muse::Ret toggleMetronome() override;
      95              : 
      96              :     muse::Ret toggleMidiInput() override;
      97              :     muse::Ret setMidiUseWrittenPitch(bool useWrittenPitch) override;
      98              : 
      99              :     muse::Ret togglePlayRepeats() override;
     100              :     muse::Ret togglePlayChordSymbols() override;
     101              :     muse::Ret toggleAutomaticallyPan() override;
     102              :     muse::Ret toggleCountIn() override;
     103              :     muse::Ret toggleHearPlaybackWhenEditing() override;
     104              : 
     105              :     muse::Ret reloadPlaybackCache() override;
     106              : 
     107              :     const InstrumentTrackIdMap& instrumentTrackIdMap() const override;
     108              :     const AuxTrackIdMap& auxTrackIdMap() const override;
     109              : 
     110              :     muse::async::Channel<muse::audio::TrackId> trackAdded() const override;
     111              :     muse::async::Channel<muse::audio::TrackId> trackRemoved() const override;
     112              : 
     113              :     std::string auxChannelName(muse::audio::aux_channel_idx_t index) const override;
     114              :     muse::async::Channel<muse::audio::aux_channel_idx_t, std::string> auxChannelNameChanged() const override;
     115              : 
     116              :     muse::async::Promise<muse::audio::SoundPresetList> availableSoundPresets(
     117              :         const engraving::InstrumentTrackId& instrumentTrackId) const override;
     118              : 
     119              :     const SoloMuteState& trackSoloMuteState(const engraving::InstrumentTrackId& trackId) const override;
     120              :     void setTrackSoloMuteState(const engraving::InstrumentTrackId& trackId, const SoloMuteState& state) override;
     121              : 
     122              :     void playElements(const std::vector<const engraving::EngravingItem*>& elements,
     123              :                       const PlayParams& params = PlayParams(), bool isMidi = false) override;
     124              :     void playNotes(const engraving::NoteValList& notes, engraving::staff_idx_t staffIdx, const engraving::Segment* segment,
     125              :                    const PlayParams& params = PlayParams()) override;
     126              :     void playMetronome(int tick) override;
     127              : 
     128              :     void triggerControllers(const muse::mpe::ControllerChangeEventList& list, engraving::staff_idx_t staffIdx, int tick) override;
     129              : 
     130              :     void seekElement(const engraving::EngravingItem* element, bool flushSound = true) override;
     131              :     void seekBeat(int measureIndex, int beatIndex, bool flushSound = true) override;
     132              : 
     133              :     muse::secs_t totalPlayTime() const override;
     134              :     muse::async::Notification totalPlayTimeChanged() const override;
     135              : 
     136              :     const notation::Tempo& currentTempo() const override;
     137              :     muse::async::Notification currentTempoChanged() const override;
     138              : 
     139              :     engraving::MeasureBeat currentBeat() const override;
     140              :     muse::audio::secs_t beatToSecs(int measureIndex, int beatIndex) const override;
     141              : 
     142              :     double tempoMultiplier() const override;
     143              :     void setTempoMultiplier(double multiplier) override;
     144              : 
     145              :     muse::Progress loadingProgress() const override;
     146              : 
     147              :     void applyProfile(const SoundProfileName& profileName) override;
     148              : 
     149              :     void setNotation(notation::INotationPtr notation) override;
     150              :     void setMasterNotation(notation::IMasterNotationPtr masterNotation);
     151              : 
     152              :     void setIsExportingAudio(bool exporting) override;
     153              : 
     154              :     const std::map<muse::audio::TrackId, muse::audio::AudioResourceMeta>& onlineSounds() const override;
     155              :     muse::async::Notification onlineSoundsChanged() const override;
     156              :     muse::Progress onlineSoundsProcessingProgress() const override;
     157              : 
     158              : private:
     159              :     muse::audio::IPlayerPtr currentPlayer() const;
     160              : 
     161              :     notation::INotationPlaybackPtr notationPlayback() const;
     162              :     notation::INotationPartsPtr masterNotationParts() const;
     163              :     notation::INotationSelectionPtr selection() const;
     164              :     notation::INotationSelectionRangePtr selectionRange() const;
     165              :     notation::INotationInteractionPtr interaction() const;
     166              : 
     167              :     uint64_t notationPlaybackKey() const;
     168              : 
     169              :     void updateCurrentTempo();
     170              : 
     171              :     void seekRawTick(const muse::midi::tick_t tick, const bool flushSound = true);
     172              :     void seek(const muse::audio::secs_t secs, const bool flushSound = true);
     173              : 
     174              :     bool isPaused() const;
     175              :     bool isLoaded() const;
     176              : 
     177              :     bool loopBoundariesSet() const;
     178              : 
     179              :     void onNotationChanged();
     180              :     void onPartChanged(const engraving::Part* part);
     181              :     void onPlaybackStatusChanged();
     182              : 
     183              :     void onSelectionChanged();
     184              :     void seekRangeSelection();
     185              : 
     186              :     void onAudioResourceChanged(const muse::audio::TrackId trackId, const mu::engraving::InstrumentTrackId& instrumentTrackId,
     187              :                                 const muse::audio::AudioResourceMeta& oldMeta, const muse::audio::AudioResourceMeta& newMeta);
     188              : 
     189              :     bool shouldLoadDrumset(const engraving::InstrumentTrackId& instrumentTrackId, const muse::audio::AudioResourceMeta& oldMeta,
     190              :                            const muse::audio::AudioResourceMeta& newMeta) const;
     191              : 
     192              :     void addSoundFlagsIfNeed(const std::vector<engraving::EngravingItem*>& selection);
     193              : 
     194              :     void doRewind(muse::secs_t newPosition);
     195              :     void doPlay();
     196              :     void doPause(bool select = false);
     197              :     void doStop();
     198              :     void doResume();
     199              : 
     200              :     muse::audio::secs_t playbackStartSecs() const;
     201              : 
     202              :     engraving::InstrumentTrackIdSet instrumentTrackIdSetForRangePlayback() const;
     203              : 
     204              :     void addLoopBoundaryToTick(LoopBoundaryType type, int tick);
     205              :     void updateLoop();
     206              : 
     207              :     void enableLoop();
     208              :     void disableLoop();
     209              : 
     210              :     project::IProjectAudioSettingsPtr audioSettings() const;
     211              : 
     212              :     void resetPlayback();
     213              :     void setupPlaybackIfNeed();
     214              :     void setupPlayback();
     215              :     void subscribeOnAudioParamsChanges();
     216              :     void setupTracks();
     217              :     void setupPlayer();
     218              : 
     219              :     void updateSoloMuteStates();
     220              :     void updateAuxMuteStates();
     221              : 
     222              :     using TrackAddFinished = std::function<void ()>;
     223              : 
     224              :     void addTrack(const engraving::InstrumentTrackId& instrumentTrackId, bool projectHadNoAudioSettings,
     225              :                   const TrackAddFinished& onFinished);
     226              :     void doAddTrack(const engraving::InstrumentTrackId& instrumentTrackId, const std::string& title, bool projectHadNoAudioSettings,
     227              :                     const TrackAddFinished& onFinished);
     228              :     void addAuxTrack(muse::audio::aux_channel_idx_t index, bool projectHadNoAudioSettings, const TrackAddFinished& onFinished);
     229              : 
     230              :     void setTrackActivity(const engraving::InstrumentTrackId& instrumentTrackId, const bool isActive);
     231              :     project::AudioOutputParams trackOutputParams(const engraving::InstrumentTrackId& instrumentTrackId) const;
     232              : 
     233              :     muse::audio::ControlParams trackControlParams(const engraving::InstrumentTrackId& instrumentTrackId,
     234              :                                                   const project::AudioOutputParams& outParams, bool rebuildVolume = true,
     235              :                                                   bool rebuildPan = true);
     236              :     void removeTrack(const engraving::InstrumentTrackId& instrumentTrackId);
     237              : 
     238              :     void onAutomationDataChanged(const notation::AutomationChanges& changes);
     239            0 :     void resendAutomatedControlParams(std::optional<engraving::InstrumentTrackIdSet> volumeTrackIds = std::nullopt,
     240            0 :                                       std::optional<engraving::InstrumentTrackIdSet> panTrackIds = std::nullopt);
     241              : 
     242              :     void onTrackNewlyAdded(const engraving::InstrumentTrackId& instrumentTrackId);
     243              : 
     244              :     muse::audio::secs_t playedTickToSecs(int tick) const;
     245              : 
     246              :     notation::INotationPtr m_notation;
     247              :     notation::IMasterNotationPtr m_masterNotation;
     248              :     muse::audio::IPlayerPtr m_player;
     249              :     bool m_needSetupPlayback = false;
     250              :     bool m_isPlaybackInited = false;
     251              :     muse::async::Channel<bool> m_playbackInited;
     252              : 
     253              :     muse::async::Channel<bool> m_isPlayAllowedChanged;
     254              :     muse::async::Channel<bool> m_isPlayingChanged;
     255              :     muse::async::Channel<muse::audio::secs_t> m_playbackPositionChanged;
     256              :     muse::async::Channel<bool> m_loopEnabledChanged;
     257              :     muse::async::Notification m_totalPlayTimeChanged;
     258              :     muse::async::Notification m_currentTempoChanged;
     259              : 
     260              :     muse::midi::tick_t m_currentTick = 0;
     261              :     notation::Tempo m_currentTempo;
     262              : 
     263              :     muse::async::Channel<muse::audio::TrackId> m_trackAdded;
     264              :     muse::async::Channel<muse::audio::TrackId> m_trackRemoved;
     265              : 
     266              :     muse::async::Channel<muse::audio::aux_channel_idx_t, std::string> m_auxChannelNameChanged;
     267              : 
     268              :     muse::async::Asyncable m_seqAsyncReceiver; //! HACK - see PlaybackController::setupTracks
     269              : 
     270              :     InstrumentTrackIdMap m_instrumentTrackIdMap;
     271              :     AuxTrackIdMap m_auxTrackIdMap;
     272              : 
     273              :     std::unordered_map<engraving::InstrumentTrackId, muse::audio::ControlParams> m_automatedControlParamsCache;
     274              : 
     275              :     muse::Progress m_loadingProgress;
     276              :     size_t m_loadingTrackCount = 0;
     277              : 
     278              :     bool m_isExportingAudio = false;
     279              :     bool m_isRangeSelection = false;
     280              : 
     281              :     DrumsetLoader m_drumsetLoader;
     282              :     std::unique_ptr<OnlineSoundsController> m_onlineSoundsController;
     283              : 
     284              :     bool m_measureInputLag = false;
     285              : };
     286              : }
        

Generated by: LCOV version 2.0-1