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 :
23 : #pragma once
24 :
25 : #include <array>
26 : #include <memory>
27 :
28 : #include "../infrastructure/ifileinfoprovider.h"
29 : #include "../infrastructure/eidregister.h"
30 :
31 : #include "instrument.h"
32 : #include "score.h"
33 :
34 : namespace mu::engraving {
35 : class EngravingProject;
36 : class MscReader;
37 : class MscWriter;
38 : class MscLoader;
39 : class TransactionManager;
40 : }
41 :
42 : namespace mu::engraving::compat {
43 : class ScoreAccess;
44 : class ReadStyleHook;
45 : }
46 :
47 : namespace mu::engraving {
48 : class Excerpt;
49 : class MasterScore;
50 : class Part;
51 : class RepeatList;
52 : struct RepeatSegmentInfo;
53 : class Revisions;
54 : class TempoTimeline;
55 : class TimeSigMap;
56 : class UndoStack;
57 : class ScoreAutomationController;
58 :
59 : class MidiMapping
60 : {
61 : public:
62 8380 : Part* part() { return m_part; }
63 : const Part* part() const { return m_part; }
64 12390 : InstrChannel* articulation() { return m_articulation.get(); }
65 103 : const InstrChannel* articulation() const { return m_articulation.get(); }
66 18533 : signed char port() const { return m_port; }
67 13486 : signed char channel() const { return m_channel; }
68 :
69 : private:
70 :
71 : MidiMapping() = default; // should be created only within MasterScore
72 : friend class MasterScore;
73 :
74 : Part* m_part = nullptr;
75 : std::unique_ptr<InstrChannel> m_articulation;
76 : signed char m_port = 0;
77 : signed char m_channel = 0;
78 : InstrChannel* m_masterChannel = nullptr;
79 : PartChannelSettingsLink m_link;
80 : };
81 :
82 : class MasterScore : public Score
83 : {
84 4113 : OBJECT_ALLOCATOR(engraving, MasterScore)
85 :
86 : public:
87 :
88 : ~MasterScore();
89 : MasterScore* clone();
90 :
91 : Score* createScore();
92 : Score* createScore(const MStyle& s);
93 :
94 0 : std::weak_ptr<EngravingProject> project() const { return m_project; }
95 :
96 32154 : bool isMaster() const override { return true; }
97 :
98 475764 : EIDRegister* eidRegister() { return &m_eidRegister; }
99 : const EIDRegister* eidRegister() const { return &m_eidRegister; }
100 :
101 1468 : bool readOnly() const override { return m_readOnly; }
102 : void setReadOnly(bool ro) { m_readOnly = ro; }
103 50843 : TransactionManager* transactionManager() const { return m_transactionManager.get(); }
104 4691 : UndoStack* undoStack() const { return m_undoStack; }
105 11824 : TimeSigMap* sigmap() const override { return m_sigmap; }
106 997 : muse::async::Channel<ScoreChanges> changesChannel() const override { return m_changesChannel; }
107 :
108 : AutomationDataConstPtr automationData() const override;
109 : void setAutomationData(AutomationDataPtr data);
110 : void editAutomationPoints(const AutomationCurveKey& key, AutomationPointEdits& edits, bool undoable = true) override;
111 :
112 : /// Always call this before calling `repeatList()`
113 : /// No need to set it back after use, because everyone always calls it before using `repeatList()`
114 : void setExpandRepeats(bool expandRepeats);
115 8644 : bool expandRepeats() const { return m_expandRepeats; }
116 :
117 : void updateRepeatListTempo();
118 : void updateRepeatList();
119 :
120 : const RepeatList& repeatList() const;
121 : const RepeatList& repeatList(bool expandRepeats, bool updateTies = true) const;
122 :
123 : void invalidateRepeatList();
124 :
125 : const TempoTimeline& tempoTimeline() const;
126 : const TempoTimeline& tempoTimeline(bool expandRepeats) const;
127 : bool setTempoMultiplier(BeatsPerSecond val);
128 : void setTempoTimelineOverride(std::optional<TempoTimeline> timeline);
129 :
130 15206 : std::vector<Excerpt*>& excerpts() { return m_excerpts; }
131 0 : const std::vector<Excerpt*>& excerpts() const { return m_excerpts; }
132 :
133 : void setUpdateAll() override;
134 :
135 : void setLayoutAll(staff_idx_t staff = muse::nidx, const EngravingItem* e = nullptr);
136 : void setLayout(const Fraction& tick, staff_idx_t staff, const EngravingItem* e = nullptr);
137 : void setLayout(const Fraction& tick1, const Fraction& tick2, staff_idx_t staff1, staff_idx_t staff2, const EngravingItem* e = nullptr);
138 :
139 264484 : CmdState& cmdState() override { return m_cmdState; }
140 0 : const CmdState& cmdState() const override { return m_cmdState; }
141 274 : void addLayoutFlags(LayoutFlags val) override { m_cmdState.layoutFlags |= val; }
142 103 : void setInstrumentsChanged(bool val) override { m_cmdState.instrumentsChanged = val; }
143 :
144 1170 : void setExcerptsChanged(bool val) { m_cmdState.excerptsChanged = val; }
145 0 : bool excerptsChanged() const { return m_cmdState.excerptsChanged; }
146 : bool instrumentsChanged() const { return m_cmdState.instrumentsChanged; }
147 :
148 87 : void update() { update(true); }
149 : void lockUpdates(bool locked);
150 :
151 : int midiPortCount() const { return m_midiPortCount; }
152 3022 : void setMidiPortCount(int val) { m_midiPortCount = val; }
153 16 : std::vector<MidiMapping>& midiMapping() { return m_midiMapping; }
154 3931 : MidiMapping* midiMapping(int channel) { return &m_midiMapping[channel]; }
155 : void addMidiMapping(InstrChannel* channel, Part* part, int midiPort, int midiChannel);
156 : void updateMidiMapping(InstrChannel* channel, Part* part, int midiPort, int midiChannel);
157 1712 : int midiPort(int idx) const { return m_midiMapping[idx].port(); }
158 3001 : int midiChannel(int idx) const { return m_midiMapping[idx].channel(); }
159 : void rebuildMidiMapping();
160 : void checkMidiMapping();
161 1966 : bool exportMidiMapping() { return !m_isSimpleMidiMapping; }
162 : int getNextFreeMidiMapping(std::set<int>& occupiedMidiChannels, unsigned int& searchMidiMappingFrom, int p = -1, int ch = -1);
163 : int getNextFreeDrumMidiMapping(std::set<int>& occupiedMidiChannels);
164 : void rebuildAndUpdateExpressive(Synthesizer* synth);
165 : void updateExpressive(Synthesizer* synth);
166 : void updateExpressive(Synthesizer* synth, bool expressive, bool force = false);
167 :
168 : using Score::loopBoundaryTick;
169 : Fraction loopBoundaryTick(LoopBoundaryType type) const;
170 : void setLoopBoundaryTick(LoopBoundaryType type, Fraction tick);
171 :
172 : void addExcerpt(Excerpt*, size_t index = muse::nidx);
173 : void removeExcerpt(Excerpt*);
174 : void deleteExcerpt(Excerpt*);
175 :
176 : void initAndAddExcerpt(Excerpt*, bool);
177 : void initExcerpt(Excerpt*);
178 : void initEmptyExcerpt(Excerpt*);
179 :
180 : void initAutomation(); // TODO: Placeholder?
181 :
182 : void setPlaybackScore(Score*);
183 0 : Score* playbackScore() { return m_playbackScore; }
184 : const Score* playbackScore() const { return m_playbackScore; }
185 5507 : InstrChannel* playbackChannel(const InstrChannel* c) { return m_midiMapping[c->channel()].articulation(); }
186 103 : const InstrChannel* playbackChannel(const InstrChannel* c) const { return m_midiMapping[c->channel()].articulation(); }
187 :
188 : MasterScore* unrollRepeats();
189 :
190 : MeasureBase* insertMeasure(MeasureBase* beforeMeasure = nullptr, const InsertMeasureOptions& options = InsertMeasureOptions());
191 :
192 : IFileInfoProviderPtr fileInfo() const;
193 : void setFileInfoProvider(IFileInfoProviderPtr fileInfoProvider);
194 :
195 : String name() const override;
196 :
197 : muse::Ret sanityCheck();
198 :
199 : private:
200 : void update(bool resetCmdState, bool layoutAllParts = false);
201 :
202 : void updateAutomation(const ScoreChanges& changes);
203 :
204 : void onTimeInserted(const Fraction& tick, const Fraction& len, const std::vector<RepeatSegmentInfo>& oldSegments) override;
205 :
206 : void reorderMidiMapping();
207 : void rebuildExcerptsMidiMapping();
208 : void removeDeletedMidiMapping();
209 :
210 : int updateMidiMapping();
211 : void doUpdateMidiMapping(int& maxport, std::set<int>& occupiedMidiChannels, unsigned int& searchMidiMappingFrom, Part* part,
212 : InstrChannel* channel, bool useDrumset);
213 :
214 : friend class EngravingProject;
215 : friend class compat::ScoreAccess;
216 : friend class read114::Read114;
217 : friend class read400::Read400;
218 : friend class TransactionManager;
219 :
220 : MasterScore(const muse::modularity::ContextPtr& iocCtx, std::weak_ptr<EngravingProject> project = std::weak_ptr<EngravingProject>());
221 : MasterScore(const muse::modularity::ContextPtr& iocCtx, const MStyle&,
222 : std::weak_ptr<EngravingProject> project = std::weak_ptr<EngravingProject>());
223 :
224 : void initParts(Excerpt*);
225 :
226 : EIDRegister m_eidRegister;
227 : std::unique_ptr<TransactionManager> m_transactionManager;
228 : UndoStack* m_undoStack = nullptr;
229 : TimeSigMap* m_sigmap = nullptr;
230 : RepeatList* m_expandedRepeatList = nullptr;
231 : RepeatList* m_nonExpandedRepeatList = nullptr;
232 : ScoreAutomationController* m_automationController = nullptr;
233 : bool m_expandRepeats = true;
234 :
235 : std::vector<Excerpt*> m_excerpts;
236 : std::vector<PartChannelSettingsLink> m_playbackSettingsLinks;
237 : Score* m_playbackScore = nullptr;
238 : muse::async::Channel<ScoreChanges> m_changesChannel;
239 :
240 : bool m_readOnly = false;
241 :
242 : CmdState m_cmdState; // modified during cmd processing
243 : bool m_updatesLocked = false;
244 :
245 : std::array<Fraction, 2> m_loopBoundaries; ///< 0 - LoopIn, 1 - LoopOut
246 :
247 : int m_midiPortCount = 0; // A count of ALSA midi out ports
248 : std::vector<MidiMapping> m_midiMapping;
249 : bool m_isSimpleMidiMapping = false; // midi mapping is simple if all ports and channels
250 : // don't decrease and don't have gaps
251 :
252 : std::weak_ptr<EngravingProject> m_project;
253 :
254 : // FIXME: Move to EngravingProject
255 : // We can't yet, because m_project is not set on every MasterScore
256 : IFileInfoProviderPtr m_fileInfoProvider;
257 : };
258 : }
|