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 : #include "instrument.h"
24 :
25 : #include "engraving/compat/midi/midipatch.h"
26 : #include "engraving/dom/drumset.h"
27 : #include "engraving/dom/part.h"
28 : #include "engraving/dom/masterscore.h"
29 :
30 : #include "engraving/editing/editpart.h"
31 :
32 : using namespace mu::engraving::apiv1;
33 :
34 : //---------------------------------------------------------
35 : // Channel::activeChannel
36 : //---------------------------------------------------------
37 :
38 0 : mu::engraving::InstrChannel* Channel::activeChannel()
39 : {
40 0 : mu::engraving::Score* score = m_part->score();
41 0 : mu::engraving::MasterScore* masterScore = score->masterScore();
42 :
43 0 : if (masterScore->playbackScore() == score) {
44 0 : return masterScore->playbackChannel(m_channel);
45 : }
46 0 : return m_channel;
47 : }
48 :
49 : //---------------------------------------------------------
50 : // Channel::setMidiBankAndProgram
51 : //---------------------------------------------------------
52 :
53 0 : void Channel::setMidiBankAndProgram(int bank, int program, bool setUserBankController)
54 : {
55 0 : mu::engraving::InstrChannel* ch = activeChannel();
56 :
57 0 : MidiPatch patch;
58 : // other values are unused in ChangePatch command
59 0 : patch.synti = ch->synti();
60 0 : patch.bank = bank;
61 0 : patch.prog = program;
62 :
63 0 : mu::engraving::Score* score = m_part->score();
64 0 : score->undo(new ChangePatch(score, ch, patch));
65 :
66 0 : if (setUserBankController) {
67 0 : score->undo(new SetUserBankController(ch, true));
68 : }
69 0 : }
70 :
71 : //---------------------------------------------------------
72 : // Channel::setMidiProgram
73 : //---------------------------------------------------------
74 :
75 0 : void Channel::setMidiProgram(int prog)
76 : {
77 0 : prog = qBound(0, prog, 127);
78 0 : setMidiBankAndProgram(activeChannel()->bank(), prog, false);
79 0 : }
80 :
81 : //---------------------------------------------------------
82 : // Channel::setMidiBank
83 : //---------------------------------------------------------
84 :
85 0 : void Channel::setMidiBank(int bank)
86 : {
87 0 : bank = qBound(0, bank, 255);
88 0 : setMidiBankAndProgram(bank, activeChannel()->program(), true);
89 0 : }
90 :
91 : //---------------------------------------------------------
92 : // StringData::stringList
93 : //---------------------------------------------------------
94 :
95 0 : QVariantList StringData::stringList() const
96 : {
97 0 : QVariantList pluginStringsList;
98 0 : for (instrString str : m_data.stringList()) {
99 0 : QVariantMap pluginStringData;
100 0 : pluginStringData["pitch"] = str.pitch;
101 0 : pluginStringData["open"] = str.open;
102 0 : pluginStringsList.append(pluginStringData);
103 0 : }
104 0 : return pluginStringsList;
105 0 : }
106 :
107 : //---------------------------------------------------------
108 : // Drumset setters
109 : // These allow modifying a cloned drumset before passing
110 : // it to Score::replaceDrumset(). The Drumset obtained
111 : // from an Instrument is read-only; Instrument::cloneDrumset()
112 : // returns a writable copy that can be modified with these
113 : // setters and then applied to the score.
114 : //---------------------------------------------------------
115 :
116 1 : void Drumset::setName(int pitch, const QString& name)
117 : {
118 1 : IF_ASSERT_FAILED(pitch >= 0 && pitch < DRUM_INSTRUMENTS) {
119 0 : return;
120 : }
121 1 : m_drumset->drum(pitch).name = name;
122 : }
123 :
124 0 : void Drumset::setNoteHead(int pitch, int noteHead)
125 : {
126 0 : IF_ASSERT_FAILED(pitch >= 0 && pitch < DRUM_INSTRUMENTS) {
127 0 : return;
128 : }
129 0 : m_drumset->drum(pitch).notehead = mu::engraving::NoteHeadGroup(noteHead);
130 : }
131 :
132 0 : void Drumset::setLine(int pitch, int line)
133 : {
134 0 : IF_ASSERT_FAILED(pitch >= 0 && pitch < DRUM_INSTRUMENTS) {
135 0 : return;
136 : }
137 0 : m_drumset->drum(pitch).line = line;
138 : }
139 :
140 0 : void Drumset::setVoice(int pitch, int voice)
141 : {
142 0 : IF_ASSERT_FAILED(pitch >= 0 && pitch < DRUM_INSTRUMENTS) {
143 0 : return;
144 : }
145 0 : m_drumset->drum(pitch).voice = voice;
146 : }
147 :
148 0 : void Drumset::setStemDirection(int pitch, int stemDirection)
149 : {
150 0 : IF_ASSERT_FAILED(pitch >= 0 && pitch < DRUM_INSTRUMENTS) {
151 0 : return;
152 : }
153 0 : m_drumset->drum(pitch).stemDirection = mu::engraving::DirectionV(stemDirection);
154 : }
155 :
156 0 : void Drumset::setShortcut(int pitch, const QString& shortcut)
157 : {
158 0 : IF_ASSERT_FAILED(pitch >= 0 && pitch < DRUM_INSTRUMENTS) {
159 0 : return;
160 : }
161 0 : m_drumset->drum(pitch).shortcut = shortcut;
162 : }
163 :
164 : //---------------------------------------------------------
165 : // Drumset::variants
166 : //---------------------------------------------------------
167 :
168 0 : QVariantList Drumset::variants(int pitch)
169 : {
170 0 : QVariantList drumInstrumentVariantList;
171 0 : for (const DrumInstrumentVariant& div : m_drumset->variants(pitch)) {
172 0 : QVariantMap pluginDivData;
173 0 : pluginDivData["pitch"] = div.pitch;
174 0 : pluginDivData["tremolo"] = int(div.tremolo);
175 0 : pluginDivData["articulationName"] = div.articulationName.toQString();
176 0 : drumInstrumentVariantList.append(pluginDivData);
177 0 : }
178 0 : return drumInstrumentVariantList;
179 0 : }
180 :
181 : //---------------------------------------------------------
182 : // ChannelListProperty
183 : //---------------------------------------------------------
184 :
185 0 : ChannelListProperty::ChannelListProperty(Instrument* i)
186 0 : : QQmlListProperty<Channel>(i, i, nullptr, &count, &at, nullptr) {}
187 :
188 : //---------------------------------------------------------
189 : // ChannelListProperty::count
190 : //---------------------------------------------------------
191 :
192 0 : qsizetype ChannelListProperty::count(QQmlListProperty<Channel>* l)
193 : {
194 0 : return static_cast<Instrument*>(l->data)->instrument()->channel().size();
195 : }
196 :
197 : //---------------------------------------------------------
198 : // ChannelListProperty::at
199 : //---------------------------------------------------------
200 :
201 0 : Channel* ChannelListProperty::at(QQmlListProperty<Channel>* l, qsizetype i)
202 : {
203 0 : Instrument* instr = static_cast<Instrument*>(l->data);
204 :
205 0 : if (i < 0 || size_t(i) >= instr->instrument()->channel().size()) {
206 0 : return nullptr;
207 : }
208 :
209 0 : mu::engraving::InstrChannel* ch = instr->instrument()->channel(i);
210 :
211 0 : return customWrap<Channel>(ch, instr->part());
212 : }
213 :
214 : //---------------------------------------------------------
215 : // Instrument::longName
216 : //---------------------------------------------------------
217 :
218 0 : QString Instrument::longName() const
219 : {
220 0 : return instrument()->longName().toQString();
221 : }
222 :
223 : //---------------------------------------------------------
224 : // Instrument::shortName
225 : //---------------------------------------------------------
226 :
227 0 : QString Instrument::shortName() const
228 : {
229 0 : return instrument()->shortName().toQString();
230 : }
231 :
232 : //---------------------------------------------------------
233 : // Instrument::channels
234 : //---------------------------------------------------------
235 :
236 1 : Drumset* Instrument::cloneDrumset()
237 : {
238 1 : const mu::engraving::Drumset* ds = instrument()->drumset();
239 1 : if (!ds) {
240 0 : return nullptr;
241 : }
242 :
243 1 : return new Drumset(new mu::engraving::Drumset(*ds), true, this);
244 : }
245 :
246 0 : ChannelListProperty Instrument::channels()
247 : {
248 0 : return ChannelListProperty(this);
249 : }
|