1 //============================================================================= 2 // MuseScore 3 // Music Composition & Notation 4 // 5 // Copyright (C) 2020 MuseScore BVBA 6 // 7 // This program is free software; you can redistribute it and/or modify 8 // it under the terms of the GNU General Public License version 2. 9 // 10 // This program is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with this program; if not, write to the Free Software 17 // Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 //============================================================================= 19 20 #ifndef __PLUGIN_API_INSTRUMENT_H__ 21 #define __PLUGIN_API_INSTRUMENT_H__ 22 23 #include "scoreelement.h" 24 #include "libmscore/instrument.h" 25 26 namespace Ms { 27 28 class Instrument; 29 30 namespace PluginAPI { 31 32 class Instrument; 33 34 //--------------------------------------------------------- 35 // Channel 36 /// Provides an access to channel properties. Similar to 37 /// Mixer, changes to some of the playback-related 38 /// properties are not recorded to undo stack and are not 39 /// revertable with standard user-visible "undo" action. 40 /// Changing MIDI patch though is undoable in normal way 41 /// ("dock" type plugins may need to call 42 /// \ref Score.startCmd / \ref Score.endCmd for that to 43 /// work properly). 44 /// 45 /// Iterating over all channels in the current score can 46 /// be done as follows: 47 /// \code 48 /// var parts = curScore.parts; 49 /// for (var i = 0; i < parts.length; ++i) { 50 /// var part = parts[i]; 51 /// var instrs = part.instruments; 52 /// for (var j = 0; j < instrs.length; ++j) { 53 /// var instr = instrs[j]; 54 /// var channels = instr.channels; 55 /// for (var k = 0; k < channels.length; ++k) { 56 /// var channel = channels[k]; 57 /// channel.volume = 64; // just for example, changing the channel's volume 58 /// } 59 /// } 60 /// } 61 /// \endcode 62 /// \since MuseScore 3.5 63 //--------------------------------------------------------- 64 65 class Channel : public QObject { 66 Q_OBJECT 67 68 Ms::Channel* _channel; 69 Ms::Part* _part; 70 71 /** Name of this channel */ 72 Q_PROPERTY(QString name READ name) 73 74 /** 75 * Channel volume, from 0 to 127. 76 * \note Changing this property is **not** revertable with a standard "undo" 77 * action. Plugins may need to handle reverting this property change if 78 * necessary. 79 */ 80 Q_PROPERTY(int volume READ volume WRITE setVolume) 81 /** 82 * Channel pan, from 0 to 127. 83 * \note Changing this property is **not** revertable with a standard "undo" 84 * action. Plugins may need to handle reverting this property change if 85 * necessary. 86 */ 87 Q_PROPERTY(int pan READ pan WRITE setPan) 88 /** 89 * Channel chorus, from 0 to 127. 90 * \note Changing this property is **not** revertable with a standard "undo" 91 * action. Plugins may need to handle reverting this property change if 92 * necessary. 93 */ 94 Q_PROPERTY(int chorus READ chorus WRITE setChorus) 95 /** 96 * Channel reverb, from 0 to 127. 97 * \note Changing this property is **not** revertable with a standard "undo" 98 * action. Plugins may need to handle reverting this property change if 99 * necessary. 100 */ 101 Q_PROPERTY(int reverb READ reverb WRITE setReverb) 102 /** 103 * Whether this channel is muted. 104 * \note Changing this property is **not** revertable with a standard "undo" 105 * action. Plugins may need to handle reverting this property change if 106 * necessary. 107 */ 108 Q_PROPERTY(bool mute READ mute WRITE setMute) 109 110 /** 111 * MIDI program number, from 0 to 127. Changing this property is recorded 112 * to the program's undo stack and can be reverted with a standard "undo" 113 * action. 114 */ 115 Q_PROPERTY(int midiProgram READ midiProgram WRITE setMidiProgram) 116 /** 117 * MIDI patch bank number. Changing this property is recorded 118 * to the program's undo stack and can be reverted with a standard "undo" 119 * action. 120 */ 121 Q_PROPERTY(int midiBank READ midiBank WRITE setMidiBank) 122 123 Ms::Channel* activeChannel(); 124 125 void setMidiBankAndProgram(int bank, int program, bool setUserBankController); 126 127 public: 128 /// \cond MS_INTERNAL 129 Channel(Ms::Channel* ch, Ms::Part* p, QObject* parent = nullptr) QObject(parent)130 : QObject(parent), _channel(ch), _part(p) {} 131 name()132 QString name() const { return _channel->name(); } 133 volume()134 int volume() const { return _channel->volume(); } setVolume(int val)135 void setVolume(int val) { activeChannel()->setVolume(qBound(0, val, 127)); } pan()136 int pan() const { return _channel->pan(); } setPan(int val)137 void setPan(int val) { activeChannel()->setPan(qBound(0, val, 127)); } chorus()138 int chorus() const { return _channel->chorus(); } setChorus(int val)139 void setChorus(int val) { activeChannel()->setChorus(qBound(0, val, 127)); } reverb()140 int reverb() const { return _channel->reverb(); } setReverb(int val)141 void setReverb(int val) { activeChannel()->setReverb(qBound(0, val, 127)); } 142 mute()143 bool mute() const { return _channel->mute(); } setMute(bool val)144 void setMute(bool val) { activeChannel()->setMute(val); } 145 midiProgram()146 int midiProgram() const { return _channel->program(); } 147 void setMidiProgram(int prog); midiBank()148 int midiBank() const { return _channel->bank(); } 149 void setMidiBank(int bank); 150 /// \endcond 151 }; 152 153 //--------------------------------------------------------- 154 // StringData 155 /// \since MuseScore 3.5 156 //--------------------------------------------------------- 157 158 class StringData : public QObject { 159 Q_OBJECT 160 161 /** 162 * List of strings in this instrument. 163 * \returns A list of objects representing strings. Each 164 * object has the following fields: 165 * - \p pitch - pitch of this string on fret 0 (integer). 166 * - \p open - if \p true, this string is not fretted and 167 * always open. If \p false, the string **is** 168 * fretted. For example, for classical guitar 169 * all strings are fretted, and for them 170 * \p open value will always be \p false. 171 */ 172 Q_PROPERTY(QVariantList strings READ stringList) 173 174 /** Number of frets in this instrument */ 175 Q_PROPERTY(int frets READ frets) 176 177 Ms::StringData _data; 178 179 public: 180 /// \cond MS_INTERNAL 181 StringData(const Ms::StringData* d, QObject* parent = nullptr) QObject(parent)182 : QObject(parent), _data(*d) {} 183 184 QVariantList stringList() const; frets()185 int frets() const { return _data.frets(); } 186 /// \endcond 187 }; 188 189 //--------------------------------------------------------- 190 // ChannelListProperty 191 /// \cond PLUGIN_API \private \endcond 192 //--------------------------------------------------------- 193 194 class ChannelListProperty : public QQmlListProperty<Channel> { 195 public: 196 ChannelListProperty(Instrument* i); 197 198 static int count(QQmlListProperty<Channel>* l); 199 static Channel* at(QQmlListProperty<Channel>* l, int i); 200 }; 201 202 //--------------------------------------------------------- 203 // Instrument 204 /// \since MuseScore 3.5 205 //--------------------------------------------------------- 206 207 class Instrument : public QObject { 208 Q_OBJECT 209 210 /** 211 * The string identifier 212 * ([MusicXML Sound ID](https://www.musicxml.com/for-developers/standard-sounds/)) 213 * for this instrument. 214 * \see \ref Ms::PluginAPI::Part::instrumentId "Part.instrumentId" 215 */ 216 Q_PROPERTY(QString instrumentId READ instrumentId) 217 // Ms::Instrument supports multiple short/long names (for aeolus instruments?) 218 // but in practice only one is actually used. If this gets changed this API could 219 // be expanded. 220 /** The long name for this instrument. */ 221 Q_PROPERTY(QString longName READ longName) 222 /** The short name for this instrument. */ 223 Q_PROPERTY(QString shortName READ shortName) 224 225 /** 226 * For fretted instruments, an information about this 227 * instrument's strings. 228 */ 229 Q_PROPERTY(Ms::PluginAPI::StringData* stringData READ stringData) 230 231 // TODO: a property for drumset? 232 233 Q_PROPERTY(QQmlListProperty<Ms::PluginAPI::Channel> channels READ channels) 234 235 Ms::Instrument* _instrument; 236 Ms::Part* _part; 237 238 public: 239 /// \cond MS_INTERNAL Instrument(Ms::Instrument * i,Ms::Part * p)240 Instrument(Ms::Instrument* i, Ms::Part* p) 241 : QObject(), _instrument(i), _part(p) {} 242 instrument()243 Ms::Instrument* instrument() { return _instrument; } instrument()244 const Ms::Instrument* instrument() const { return _instrument; } 245 part()246 Ms::Part* part() { return _part; } 247 instrumentId()248 QString instrumentId() const { return instrument()->instrumentId(); } 249 QString longName() const; 250 QString shortName() const; 251 stringData()252 StringData* stringData() { return customWrap<StringData>(instrument()->stringData()); } 253 254 ChannelListProperty channels(); 255 /// \endcond 256 257 /** Checks whether two variables represent the same object. */ is(Ms::PluginAPI::Instrument * other)258 Q_INVOKABLE bool is(Ms::PluginAPI::Instrument* other) { return other && instrument() == other->instrument(); } 259 }; 260 261 } // namespace PluginAPI 262 } // namespace Ms 263 264 #endif 265