1 //=============================================================================
2 // MuseScore
3 // Music Composition & Notation
4 //
5 // Copyright (C) 2008-2011 Werner Schweer
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 // as published by the Free Software Foundation and appearing in
10 // the file LICENCE.GPL
11 //=============================================================================
12
13 #include "instrument.h"
14 #include "xml.h"
15 #include "drumset.h"
16 #include "articulation.h"
17 #include "utils.h"
18 #include "stringdata.h"
19 #include "instrtemplate.h"
20 #include "mscore.h"
21 #include "part.h"
22 #include "score.h"
23
24 #include "audio/midi/synthesizer.h"
25 #include "audio/midi/midipatch.h"
26
27 namespace Ms {
28
29 //: Channel name for otherwise unamed channels
30 const char* Channel::DEFAULT_NAME = QT_TRANSLATE_NOOP("InstrumentsXML", "normal");
31 //: Channel name for the chord symbols playback channel, best keep translation shorter than 11 letters
32 const char* Channel::HARMONY_NAME = QT_TRANSLATE_NOOP("InstrumentsXML", "harmony");
33
34 Instrument InstrumentList::defaultInstrument;
35 const std::initializer_list<Channel::Prop> PartChannelSettingsLink::excerptProperties {
36 Channel::Prop::SOLOMUTE,
37 Channel::Prop::SOLO,
38 Channel::Prop::MUTE,
39 };
40
41 //---------------------------------------------------------
42 // write
43 //---------------------------------------------------------
44
write(XmlWriter & xml,const QString & n) const45 void NamedEventList::write(XmlWriter& xml, const QString& n) const
46 {
47 xml.stag(QString("%1 name=\"%2\"").arg(n, name));
48 if (!descr.isEmpty())
49 xml.tag("descr", descr);
50 for (const MidiCoreEvent& e : events)
51 e.write(xml);
52 xml.etag();
53 }
54
55 //---------------------------------------------------------
56 // read
57 //---------------------------------------------------------
58
read(XmlReader & e)59 void NamedEventList::read(XmlReader& e)
60 {
61 name = e.attribute("name");
62 while (e.readNextStartElement()) {
63 const QStringRef& tag(e.name());
64 if (tag == "program") {
65 MidiCoreEvent ev(ME_CONTROLLER, 0, CTRL_PROGRAM, e.intAttribute("value", 0));
66 events.push_back(ev);
67 e.skipCurrentElement();
68 }
69 else if (tag == "controller") {
70 MidiCoreEvent ev;
71 ev.setType(ME_CONTROLLER);
72 ev.setDataA(e.intAttribute("ctrl", 0));
73 ev.setDataB(e.intAttribute("value", 0));
74 events.push_back(ev);
75 e.skipCurrentElement();
76 }
77 else if (tag == "descr")
78 descr = e.readElementText();
79 else
80 e.unknown();
81 }
82 }
83
84 //---------------------------------------------------------
85 // operator
86 //---------------------------------------------------------
87
operator ==(const MidiArticulation & i) const88 bool MidiArticulation::operator==(const MidiArticulation& i) const
89 {
90 return (i.name == name) && (i.velocity == velocity) && (i.gateTime == gateTime);
91 }
92
93 //---------------------------------------------------------
94 // Instrument
95 //---------------------------------------------------------
96
Instrument(QString id)97 Instrument::Instrument(QString id)
98 {
99 _id = id;
100 Channel* a = new Channel;
101 a->setName(Channel::DEFAULT_NAME);
102 _channel.append(a);
103
104 _minPitchA = 0;
105 _maxPitchA = 127;
106 _minPitchP = 0;
107 _maxPitchP = 127;
108 _useDrumset = false;
109 _drumset = 0;
110 _singleNoteDynamics = true;
111 }
112
Instrument(const Instrument & i)113 Instrument::Instrument(const Instrument& i)
114 {
115 _id = i._id;
116 _longNames = i._longNames;
117 _shortNames = i._shortNames;
118 _trackName = i._trackName;
119 _minPitchA = i._minPitchA;
120 _maxPitchA = i._maxPitchA;
121 _minPitchP = i._minPitchP;
122 _maxPitchP = i._maxPitchP;
123 _transpose = i._transpose;
124 _instrumentId = i._instrumentId;
125 _stringData = i._stringData;
126 _drumset = 0;
127 setDrumset(i._drumset);
128 _useDrumset = i._useDrumset;
129 _stringData = i._stringData;
130 _midiActions = i._midiActions;
131 _articulation = i._articulation;
132 _singleNoteDynamics = i._singleNoteDynamics;
133 for (Channel* c : i._channel)
134 _channel.append(new Channel(*c));
135 _clefType = i._clefType;
136 }
137
operator =(const Instrument & i)138 void Instrument::operator=(const Instrument& i)
139 {
140 qDeleteAll(_channel);
141 _channel.clear();
142 delete _drumset;
143
144 _id = i._id;
145 _longNames = i._longNames;
146 _shortNames = i._shortNames;
147 _trackName = i._trackName;
148 _minPitchA = i._minPitchA;
149 _maxPitchA = i._maxPitchA;
150 _minPitchP = i._minPitchP;
151 _maxPitchP = i._maxPitchP;
152 _transpose = i._transpose;
153 _instrumentId = i._instrumentId;
154 _stringData = i._stringData;
155 _drumset = 0;
156 setDrumset(i._drumset);
157 _useDrumset = i._useDrumset;
158 _stringData = i._stringData;
159 _midiActions = i._midiActions;
160 _articulation = i._articulation;
161 _singleNoteDynamics = i._singleNoteDynamics;
162 for (Channel* c : i._channel)
163 _channel.append(new Channel(*c));
164 _clefType = i._clefType;
165 }
166
167 //---------------------------------------------------------
168 // ~Instrument
169 //---------------------------------------------------------
170
~Instrument()171 Instrument::~Instrument()
172 {
173 qDeleteAll(_channel);
174 delete _drumset;
175 }
176
177 //---------------------------------------------------------
178 // StaffName
179 //---------------------------------------------------------
180
StaffName(const QString & s,int p)181 StaffName::StaffName(const QString& s, int p) : _name(s), _pos(p)
182 {
183 Text::validateText(_name); // enforce HTML encoding
184 }
185
186 //---------------------------------------------------------
187 // StaffName::write
188 //---------------------------------------------------------
189
write(XmlWriter & xml,const char * tag) const190 void StaffName::write(XmlWriter& xml, const char* tag) const
191 {
192 if (!name().isEmpty()) {
193 if (pos() == 0)
194 xml.writeXml(QString("%1").arg(tag), name());
195 else
196 xml.writeXml(QString("%1 pos=\"%2\"").arg(tag).arg(pos()), name());
197 }
198 }
199
200 //---------------------------------------------------------
201 // read
202 //---------------------------------------------------------
203
read(XmlReader & e)204 void StaffName::read(XmlReader& e)
205 {
206 _pos = e.intAttribute("pos", 0);
207 _name = e.readXml();
208 if (_name.startsWith("<html>")) {
209 // compatibility to old html implementation:
210 _name = QTextDocumentFragment::fromHtml(_name).toPlainText();
211 }
212 }
213
214 //---------------------------------------------------------
215 // Instrument::write
216 //---------------------------------------------------------
217
write(XmlWriter & xml,const Part * part) const218 void Instrument::write(XmlWriter& xml, const Part* part) const
219 {
220 if (_id.isEmpty())
221 xml.stag("Instrument");
222 else
223 xml.stag(QString("Instrument id=\"%1\"").arg(_id));
224 _longNames.write(xml, "longName");
225 _shortNames.write(xml, "shortName");
226 // if (!_trackName.empty())
227 xml.tag("trackName", _trackName);
228 if (_minPitchP > 0)
229 xml.tag("minPitchP", _minPitchP);
230 if (_maxPitchP < 127)
231 xml.tag("maxPitchP", _maxPitchP);
232 if (_minPitchA > 0)
233 xml.tag("minPitchA", _minPitchA);
234 if (_maxPitchA < 127)
235 xml.tag("maxPitchA", _maxPitchA);
236 if (_transpose.diatonic)
237 xml.tag("transposeDiatonic", _transpose.diatonic);
238 if (_transpose.chromatic)
239 xml.tag("transposeChromatic", _transpose.chromatic);
240 if (!_instrumentId.isEmpty())
241 xml.tag("instrumentId", _instrumentId);
242 if (_useDrumset) {
243 xml.tag("useDrumset", _useDrumset);
244 _drumset->save(xml);
245 }
246 for (int i = 0; i < _clefType.size(); ++i) {
247 ClefTypeList ct = _clefType[i];
248 if (ct._concertClef == ct._transposingClef) {
249 if (ct._concertClef != ClefType::G) {
250 QString tag = ClefInfo::tag(ct._concertClef);
251 if (i)
252 xml.tag(QString("clef staff=\"%1\"").arg(i+1), tag);
253 else
254 xml.tag("clef", tag);
255 }
256 }
257 else {
258 QString tag1 = ClefInfo::tag(ct._concertClef);
259 QString tag2 = ClefInfo::tag(ct._transposingClef);
260 if (i) {
261 xml.tag(QString("concertClef staff=\"%1\"").arg(i+1), tag1);
262 xml.tag(QString("transposingClef staff=\"%1\"").arg(i+1), tag2);
263 }
264 else {
265 xml.tag("concertClef", tag1);
266 xml.tag("transposingClef", tag2);
267 }
268 }
269 }
270
271 if (_singleNoteDynamics != getSingleNoteDynamicsFromTemplate())
272 xml.tag("singleNoteDynamics", _singleNoteDynamics);
273
274 if (!(_stringData == StringData()))
275 _stringData.write(xml);
276 for (const NamedEventList& a : _midiActions)
277 a.write(xml, "MidiAction");
278 for (const MidiArticulation& a : _articulation)
279 a.write(xml);
280 for (const Channel* a : _channel)
281 a->write(xml, part);
282 xml.etag();
283 }
284
recognizeInstrumentId() const285 QString Instrument::recognizeInstrumentId() const
286 {
287 static QString defaultInstrumentId("keyboard.piano");
288
289 QList<QString> nameList;
290
291 nameList << _trackName;
292 nameList << _longNames.toStringList();
293 nameList << _shortNames.toStringList();
294
295 InstrumentTemplate* tmplByName = Ms::searchTemplateForInstrNameList(nameList);
296
297 if (tmplByName && !tmplByName->musicXMLid.isEmpty())
298 return tmplByName->musicXMLid;
299
300 if (!channel(0))
301 return defaultInstrumentId;
302
303 InstrumentTemplate* tmplMidiProgram = Ms::searchTemplateForMidiProgram(channel(0)->program(), useDrumset());
304
305 if (tmplMidiProgram && !tmplMidiProgram->musicXMLid.isEmpty())
306 return tmplMidiProgram->musicXMLid;
307
308 InstrumentTemplate* guessedTmpl = Ms::guessTemplateByNameData(nameList);
309
310 if (guessedTmpl && !guessedTmpl->musicXMLid.isEmpty())
311 return guessedTmpl->musicXMLid;
312
313 return defaultInstrumentId;
314 }
315
recognizeMidiProgram() const316 int Instrument::recognizeMidiProgram() const
317 {
318 InstrumentTemplate* tmplInstrumentId = Ms::searchTemplateForMusicXmlId(_instrumentId);
319
320 if (tmplInstrumentId && !tmplInstrumentId->channel.isEmpty() && tmplInstrumentId->channel[0].program() >= 0)
321 return tmplInstrumentId->channel[0].program();
322
323 QList<QString> nameList;
324
325 nameList << _trackName;
326 nameList << _longNames.toStringList();
327 nameList << _shortNames.toStringList();
328
329 InstrumentTemplate* tmplByName = Ms::searchTemplateForInstrNameList(nameList);
330
331 if (tmplByName && !tmplByName->channel.isEmpty() && tmplByName->channel[0].program() >= 0)
332 return tmplByName->channel[0].program();
333
334 InstrumentTemplate* guessedTmpl = Ms::guessTemplateByNameData(nameList);
335
336 if (guessedTmpl && !guessedTmpl->channel.isEmpty() && guessedTmpl->channel[0].program() >= 0)
337 return guessedTmpl->channel[0].program();
338
339 return 0;
340 }
341
342 //---------------------------------------------------------
343 // Instrument::read
344 //---------------------------------------------------------
345
read(XmlReader & e,Part * part)346 void Instrument::read(XmlReader& e, Part* part)
347 {
348 bool customDrumset = false;
349 bool readSingleNoteDynamics = false;
350
351 _channel.clear(); // remove default channel
352 _id = e.attribute("id");
353 while (e.readNextStartElement()) {
354 const QStringRef& tag(e.name());
355 if (tag == "singleNoteDynamics") {
356 _singleNoteDynamics = e.readBool();
357 readSingleNoteDynamics = true;
358 }
359 else if (!readProperties(e, part, &customDrumset))
360 e.unknown();
361 }
362
363 if (_instrumentId.isEmpty())
364 _instrumentId = recognizeInstrumentId();
365
366 if (channel(0) && channel(0)->program() == -1) {
367 channel(0)->setProgram(recognizeMidiProgram());
368 }
369
370 if (!readSingleNoteDynamics)
371 setSingleNoteDynamicsFromTemplate();
372
373 if (_useDrumset) {
374 if (_channel[0]->bank() == 0 && _channel[0]->synti().toLower() != "zerberus")
375 _channel[0]->setBank(128);
376 }
377 }
378
379 //---------------------------------------------------------
380 // Instrument::readProperties
381 //---------------------------------------------------------
382
readProperties(XmlReader & e,Part * part,bool * customDrumset)383 bool Instrument::readProperties(XmlReader& e, Part* part, bool* customDrumset)
384 {
385 const QStringRef& tag(e.name());
386 if (tag == "longName") {
387 StaffName name;
388 name.read(e);
389 _longNames.append(name);
390 }
391 else if (tag == "shortName") {
392 StaffName name;
393 name.read(e);
394 _shortNames.append(name);
395 }
396 else if (tag == "trackName")
397 _trackName = e.readElementText();
398 else if (tag == "minPitch") { // obsolete
399 _minPitchP = _minPitchA = e.readInt();
400 }
401 else if (tag == "maxPitch") { // obsolete
402 _maxPitchP = _maxPitchA = e.readInt();
403 }
404 else if (tag == "minPitchA")
405 _minPitchA = e.readInt();
406 else if (tag == "minPitchP")
407 _minPitchP = e.readInt();
408 else if (tag == "maxPitchA")
409 _maxPitchA = e.readInt();
410 else if (tag == "maxPitchP")
411 _maxPitchP = e.readInt();
412 else if (tag == "transposition") { // obsolete
413 _transpose.chromatic = e.readInt();
414 _transpose.diatonic = chromatic2diatonic(_transpose.chromatic);
415 }
416 else if (tag == "transposeChromatic")
417 _transpose.chromatic = e.readInt();
418 else if (tag == "transposeDiatonic")
419 _transpose.diatonic = e.readInt();
420 else if (tag == "instrumentId")
421 _instrumentId = e.readElementText();
422 else if (tag == "useDrumset") {
423 _useDrumset = e.readInt();
424 if (_useDrumset) {
425 delete _drumset;
426 _drumset = new Drumset(*smDrumset);
427 }
428 }
429 else if (tag == "Drum") {
430 // if we see on of this tags, a custom drumset will
431 // be created
432 if (!_drumset)
433 _drumset = new Drumset(*smDrumset);
434 if (!(*customDrumset)) {
435 const_cast<Drumset*>(_drumset)->clear();
436 *customDrumset = true;
437 }
438 const_cast<Drumset*>(_drumset)->load(e);
439 }
440 // support tag "Tablature" for a while for compatibility with existent 2.0 scores
441 else if (tag == "Tablature" || tag == "StringData")
442 _stringData.read(e);
443 else if (tag == "MidiAction") {
444 NamedEventList a;
445 a.read(e);
446 _midiActions.append(a);
447 }
448 else if (tag == "Articulation") {
449 MidiArticulation a;
450 a.read(e);
451 _articulation.append(a);
452 }
453 else if (tag == "Channel" || tag == "channel") {
454 Channel* a = new Channel;
455 a->read(e, part);
456 _channel.append(a);
457 }
458 else if (tag == "clef") { // sets both transposing and concert clef
459 int idx = e.intAttribute("staff", 1) - 1;
460 QString val(e.readElementText());
461 ClefType ct = Clef::clefType(val);
462 setClefType(idx, ClefTypeList(ct, ct));
463 }
464 else if (tag == "concertClef") {
465 int idx = e.intAttribute("staff", 1) - 1;
466 QString val(e.readElementText());
467 setClefType(idx, ClefTypeList(Clef::clefType(val), clefType(idx)._transposingClef));
468 }
469 else if (tag == "transposingClef") {
470 int idx = e.intAttribute("staff", 1) - 1;
471 QString val(e.readElementText());
472 setClefType(idx, ClefTypeList(clefType(idx)._concertClef, Clef::clefType(val)));
473 }
474 else
475 return false;
476
477 return true;
478 }
479
480 //---------------------------------------------------------
481 // action
482 //---------------------------------------------------------
483
midiAction(const QString & s,int channelIdx) const484 NamedEventList* Instrument::midiAction(const QString& s, int channelIdx) const
485 {
486 // first look in channel list
487
488 foreach(const NamedEventList& a, _channel[channelIdx]->midiActions) {
489 if (s == a.name)
490 return const_cast<NamedEventList*>(&a);
491 }
492
493 foreach(const NamedEventList& a, _midiActions) {
494 if (s == a.name)
495 return const_cast<NamedEventList*>(&a);
496 }
497 return 0;
498 }
499
500 //---------------------------------------------------------
501 // Channel
502 //---------------------------------------------------------
503
Channel()504 Channel::Channel()
505 {
506 for(int i = 0; i < int(A::INIT_COUNT); ++i)
507 _init.push_back(MidiCoreEvent());
508 _synti = "Fluid"; // default synthesizer
509 _channel = -1;
510 _program = -1;
511 _bank = 0;
512 _volume = defaultVolume;
513 _pan = 64; // actually 63.5 for center
514 _chorus = 0;
515 _reverb = 0;
516 _color = DEFAULT_COLOR;
517
518 _mute = false;
519 _solo = false;
520 _soloMute = false;
521
522 // qDebug("construct Channel ");
523 }
524
525 //---------------------------------------------------------
526 // initList
527 //---------------------------------------------------------
528
initList() const529 std::vector<MidiCoreEvent>& Channel::initList() const
530 {
531 if (_mustUpdateInit) {
532 updateInitList();
533 _mustUpdateInit = false;
534 }
535 return _init;
536 }
537
538 //---------------------------------------------------------
539 // setVolume
540 //---------------------------------------------------------
541
setVolume(char value)542 void Channel::setVolume(char value)
543 {
544 if (_volume != value) {
545 _volume = value;
546 firePropertyChanged(Prop::VOLUME);
547 }
548 _mustUpdateInit = true;
549 }
550
551 //---------------------------------------------------------
552 // setPan
553 //---------------------------------------------------------
554
setPan(char value)555 void Channel::setPan(char value)
556 {
557 if (_pan != value) {
558 _pan = value;
559 firePropertyChanged(Prop::PAN);
560 }
561 _mustUpdateInit = true;
562 }
563
564 //---------------------------------------------------------
565 // setChorus
566 //---------------------------------------------------------
567
setChorus(char value)568 void Channel::setChorus(char value)
569 {
570 if (_chorus != value) {
571 _chorus = value;
572 firePropertyChanged(Prop::CHORUS);
573 }
574 _mustUpdateInit = true;
575 }
576
577 //---------------------------------------------------------
578 // setReverb
579 //---------------------------------------------------------
580
setReverb(char value)581 void Channel::setReverb(char value)
582 {
583 if (_reverb != value) {
584 _reverb = value;
585 firePropertyChanged(Prop::REVERB);
586 }
587 _mustUpdateInit = true;
588 }
589
590 //---------------------------------------------------------
591 // setName
592 //---------------------------------------------------------
593
setName(const QString & value)594 void Channel::setName(const QString& value)
595 {
596 if (_name != value) {
597 _name = value;
598 firePropertyChanged(Prop::NAME);
599 }
600 }
601
602 //---------------------------------------------------------
603 // setDescr
604 //---------------------------------------------------------
605
setDescr(const QString & value)606 void Channel::setDescr(const QString& value)
607 {
608 if (_descr != value) {
609 _descr = value;
610 firePropertyChanged(Prop::DESCR);
611 }
612 }
613
614 //---------------------------------------------------------
615 // setSynti
616 //---------------------------------------------------------
617
setSynti(const QString & value)618 void Channel::setSynti(const QString& value)
619 {
620 if (_synti != value) {
621 _synti = value;
622 firePropertyChanged(Prop::SYNTI);
623 }
624 }
625
626 //---------------------------------------------------------
627 // setColor
628 //---------------------------------------------------------
629
setColor(int value)630 void Channel::setColor(int value)
631 {
632 if (_color != value) {
633 _color = value;
634 firePropertyChanged(Prop::COLOR);
635 }
636 }
637
638 //---------------------------------------------------------
639 // setProgram
640 //---------------------------------------------------------
641
setProgram(int value)642 void Channel::setProgram(int value)
643 {
644 if (_program != value) {
645 _program = value;
646 firePropertyChanged(Prop::PROGRAM);
647 }
648 _mustUpdateInit = true;
649 }
650
651 //---------------------------------------------------------
652 // setBank
653 //---------------------------------------------------------
654
setBank(int value)655 void Channel::setBank(int value)
656 {
657 if (_bank != value) {
658 _bank = value;
659 firePropertyChanged(Prop::BANK);
660 }
661 _mustUpdateInit = true;
662 }
663
664 //---------------------------------------------------------
665 // setChannel
666 //---------------------------------------------------------
667
setChannel(int value)668 void Channel::setChannel(int value)
669 {
670 if (_channel != value) {
671 _channel = value;
672 firePropertyChanged(Prop::CHANNEL);
673 }
674 }
675
676 //---------------------------------------------------------
677 // setSoloMute
678 //---------------------------------------------------------
679
setSoloMute(bool value)680 void Channel::setSoloMute(bool value)
681 {
682 if (_soloMute != value) {
683 _soloMute = value;
684 firePropertyChanged(Prop::SOLOMUTE);
685 }
686 }
687
688 //---------------------------------------------------------
689 // setMute
690 //---------------------------------------------------------
691
setMute(bool value)692 void Channel::setMute(bool value)
693 {
694 if (_mute != value) {
695 _mute = value;
696 firePropertyChanged(Prop::MUTE);
697 }
698 }
699
700 //---------------------------------------------------------
701 // setSolo
702 //---------------------------------------------------------
703
setSolo(bool value)704 void Channel::setSolo(bool value)
705 {
706 if (_solo != value) {
707 _solo = value;
708 firePropertyChanged(Prop::SOLO);
709 }
710 }
711
712 //---------------------------------------------------------
713 // setUserBankController
714 //---------------------------------------------------------
715
setUserBankController(bool val)716 void Channel::setUserBankController(bool val)
717 {
718 if (_userBankController != val) {
719 _userBankController = val;
720 firePropertyChanged(Prop::USER_BANK_CONTROL);
721 }
722 }
723
724 //---------------------------------------------------------
725 // write
726 //---------------------------------------------------------
727
write(XmlWriter & xml,const Part * part) const728 void Channel::write(XmlWriter& xml, const Part* part) const
729 {
730 if (_name.isEmpty() || _name == DEFAULT_NAME)
731 xml.stag("Channel");
732 else
733 xml.stag(QString("Channel name=\"%1\"").arg(_name));
734 if (!_descr.isEmpty())
735 xml.tag("descr", _descr);
736 if (_color != DEFAULT_COLOR)
737 xml.tag("color", _color);
738
739 for (const MidiCoreEvent& e : initList()) {
740 if (e.type() == ME_INVALID)
741 continue;
742 if (e.type() == ME_CONTROLLER) {
743 // Don't write bank if automatically switched, but always write if switched by the user
744 if (e.dataA() == CTRL_HBANK && e.dataB() == 0 && !_userBankController)
745 continue;
746 if (e.dataA() == CTRL_LBANK && e.dataB() == 0 && !_userBankController)
747 continue;
748 if (e.dataA() == CTRL_VOLUME && e.dataB() == 100)
749 continue;
750 if (e.dataA() == CTRL_PANPOT && e.dataB() == 64)
751 continue;
752 if (e.dataA() == CTRL_REVERB_SEND && e.dataB() == 0)
753 continue;
754 if (e.dataA() == CTRL_CHORUS_SEND && e.dataB() == 0)
755 continue;
756 }
757
758 e.write(xml);
759 }
760 if (!MScore::testMode)
761 // xml.tag("synti", ::synti->name(synti));
762 xml.tag("synti", _synti);
763 if (_mute)
764 xml.tag("mute", _mute);
765 if (_solo)
766 xml.tag("solo", _solo);
767
768 if (part && part->masterScore()->exportMidiMapping() && part->score() == part->masterScore()) {
769 xml.tag("midiPort", part->masterScore()->midiMapping(_channel)->port());
770 xml.tag("midiChannel", part->masterScore()->midiMapping(_channel)->channel());
771 }
772 for (const NamedEventList& a : midiActions)
773 a.write(xml, "MidiAction");
774 for (const MidiArticulation& a : articulation)
775 a.write(xml);
776 xml.etag();
777 }
778
779 //---------------------------------------------------------
780 // read
781 //---------------------------------------------------------
782
read(XmlReader & e,Part * part)783 void Channel::read(XmlReader& e, Part* part)
784 {
785 // synti = 0;
786 _name = e.attribute("name");
787 if (_name == "")
788 _name = DEFAULT_NAME;
789
790 int midiPort = -1;
791 int midiChannel = -1;
792
793 while (e.readNextStartElement()) {
794 const QStringRef& tag(e.name());
795 if (tag == "program") {
796 _program = e.intAttribute("value", -1);
797 if (_program == -1)
798 _program = e.readInt();
799 else
800 e.readNext();
801 }
802 else if (tag == "controller") {
803 int value = e.intAttribute("value", 0);
804 int ctrl = e.intAttribute("ctrl", 0);
805 switch (ctrl) {
806 case CTRL_HBANK:
807 _bank = (value << 7) + (_bank & 0x7f);
808 _userBankController = true;
809 break;
810 case CTRL_LBANK:
811 _bank = (_bank & ~0x7f) + (value & 0x7f);
812 _userBankController = true;
813 break;
814 case CTRL_VOLUME:
815 _volume = value;
816 break;
817 case CTRL_PANPOT:
818 _pan = value;
819 break;
820 case CTRL_CHORUS_SEND:
821 _chorus = value;
822 break;
823 case CTRL_REVERB_SEND:
824 _reverb = value;
825 break;
826 default:
827 {
828 Event ev(ME_CONTROLLER);
829 ev.setOntime(-1);
830 ev.setChannel(0);
831 ev.setDataA(ctrl);
832 ev.setDataB(value);
833 _init.push_back(ev);
834 }
835 break;
836 }
837 e.readNext();
838 }
839 else if (tag == "Articulation") {
840 MidiArticulation a;
841 a.read(e);
842 articulation.append(a);
843 }
844 else if (tag == "MidiAction") {
845 NamedEventList a;
846 a.read(e);
847 midiActions.append(a);
848 }
849 else if (tag == "synti")
850 _synti = e.readElementText();
851 else if (tag == "descr")
852 _descr = e.readElementText();
853 else if (tag == "color")
854 _color = e.readInt();
855 else if (tag == "mute")
856 _mute = e.readInt();
857 else if (tag == "solo")
858 _solo = e.readInt();
859 else if (tag == "midiPort") {
860 midiPort = e.readInt();
861 }
862 else if (tag == "midiChannel") {
863 midiChannel = e.readInt();
864 }
865 else
866 e.unknown();
867 }
868 if (128 == _bank && "zerberus" == _synti.toLower())
869 _bank = 0;
870
871 _mustUpdateInit = true;
872
873 if ((midiPort != -1 || midiChannel != -1) && part && part->score()->isMaster())
874 part->masterScore()->addMidiMapping(this, part, midiPort, midiChannel);
875 }
876
877 //---------------------------------------------------------
878 // switchExpressive
879 // Switches channel from non-expressive to expressive patch or vice versa
880 // This works only with MuseScore General soundfont
881 //---------------------------------------------------------
882
switchExpressive(Synthesizer * synth,bool expressive,bool force)883 void Channel::switchExpressive(Synthesizer* synth, bool expressive, bool force /* = false */)
884 {
885 if ((_userBankController && !force) || !synth)
886 return;
887
888 // Don't try to switch if we already have done so
889 if (expressive == _switchedToExpressive)
890 return;
891
892 // Check that we're actually changing the MuseScore General soundfont
893 const auto fontsInfo = synth->soundFontsInfo();
894 if (fontsInfo.empty())
895 return;
896 const auto& info = fontsInfo.front();
897 if (!info.fontName.contains("MuseScore_General", Qt::CaseInsensitive)) {
898 qDebug().nospace() << "Soundfont '" << info.fontName << "' is not MuseScore General, cannot update expressive";
899 return;
900 }
901
902 // Work out where the new expressive patch will be
903 // All expressive instruments are +1 bank higher than the
904 // normal counterparts, except on bank 0, where they are placed on bank 17
905 // and on bank 8, which uses bank 18 instead.
906 int searchBankNum;
907 int newBankNum;
908 if (expressive) {
909 int relativeBank = bank() % 129;
910 if (relativeBank == 0)
911 newBankNum = 17;
912 else if (relativeBank == 8)
913 newBankNum = 18;
914 else
915 newBankNum = relativeBank + 1;
916 _switchedToExpressive = true;
917 }
918 else {
919 int relativeBank = bank() % 129;
920 if (relativeBank == 17)
921 newBankNum = 0;
922 else if (relativeBank == 18)
923 newBankNum = 8;
924 else
925 newBankNum = relativeBank - 1;
926 _switchedToExpressive = false;
927 }
928
929 // Floor bank num to multiple of 129 and add new num to get bank num of new patch
930 searchBankNum = (bank() / 129) * 129 + newBankNum;
931 const auto& pl = synth->getPatchInfo();
932 for (const MidiPatch* p : pl) {
933 if (p->synti == "Fluid") {
934 if (searchBankNum == p->bank && program() == p->prog) {
935 setBank(p->bank);
936 return;
937 }
938 }
939 }
940 }
941
942 //---------------------------------------------------------
943 // updateInitList
944 //---------------------------------------------------------
945
updateInitList() const946 void Channel::updateInitList() const
947 {
948 MidiCoreEvent e;
949 if (_program != -1) {
950 e.setType(ME_CONTROLLER);
951 e.setDataA(CTRL_PROGRAM);
952 e.setDataB(_program);
953 _init[int(A::PROGRAM)] = e;
954 }
955
956 e.setData(ME_CONTROLLER, CTRL_HBANK, (_bank >> 7) & 0x7f);
957 _init[int(A::HBANK)] = e;
958
959 e.setData(ME_CONTROLLER, CTRL_LBANK, _bank & 0x7f);
960 _init[int(A::LBANK)] = e;
961
962 e.setData(ME_CONTROLLER, CTRL_VOLUME, volume());
963 _init[int(A::VOLUME)] = e;
964
965 e.setData(ME_CONTROLLER, CTRL_PANPOT, pan());
966 _init[int(A::PAN)] = e;
967
968 e.setData(ME_CONTROLLER, CTRL_CHORUS_SEND, chorus());
969 _init[int(A::CHORUS)] = e;
970
971 e.setData(ME_CONTROLLER, CTRL_REVERB_SEND, reverb());
972 _init[int(A::REVERB)] = e;
973
974 }
975
976 //---------------------------------------------------------
977 // addListener
978 //---------------------------------------------------------
979
addListener(ChannelListener * l)980 void Channel::addListener(ChannelListener* l)
981 {
982 _notifier.addListener(l);
983 }
984
985 //---------------------------------------------------------
986 // removeListener
987 //---------------------------------------------------------
988
removeListener(ChannelListener * l)989 void Channel::removeListener(ChannelListener* l)
990 {
991 _notifier.removeListener(l);
992 }
993
994 //---------------------------------------------------------
995 // PartChannelSettingsLink
996 //---------------------------------------------------------
997
PartChannelSettingsLink(Channel * main,Channel * bound,bool excerpt)998 PartChannelSettingsLink::PartChannelSettingsLink(Channel* main, Channel* bound, bool excerpt)
999 : _main(main), _bound(bound), _excerpt(excerpt)
1000 {
1001 if (excerpt) {
1002 for (Channel::Prop p : excerptProperties)
1003 applyProperty(p, /* from */ bound, /* to */ main);
1004 }
1005 // Maybe it would be good to assign common properties if the link
1006 // is constructed in non-excerpt mode. But it is not currently
1007 // necessary as playback channels are currently recreated on each
1008 // MIDI remapping.
1009
1010 main->addListener(this);
1011 }
1012
1013 //---------------------------------------------------------
1014 // PartChannelSettingsLink
1015 //---------------------------------------------------------
1016
PartChannelSettingsLink(PartChannelSettingsLink && other)1017 PartChannelSettingsLink::PartChannelSettingsLink(PartChannelSettingsLink&& other)
1018 : ChannelListener(), // swap() will set the notifier instead
1019 _main(nullptr), _bound(nullptr), _excerpt(false)
1020 {
1021 swap(*this, other);
1022 }
1023
1024 //---------------------------------------------------------
1025 // PartChannelSettingsLink::operator=
1026 //---------------------------------------------------------
1027
operator =(PartChannelSettingsLink && other)1028 PartChannelSettingsLink& PartChannelSettingsLink::operator=(PartChannelSettingsLink&& other)
1029 {
1030 if (this != &other)
1031 swap(*this, other);
1032 return *this;
1033 }
1034
1035 //---------------------------------------------------------
1036 // swap
1037 //---------------------------------------------------------
1038
swap(PartChannelSettingsLink & l1,PartChannelSettingsLink & l2)1039 void swap(PartChannelSettingsLink& l1, PartChannelSettingsLink& l2)
1040 {
1041 Ms::swap(static_cast<ChannelListener&>(l1), static_cast<ChannelListener&>(l2));
1042 using std::swap;
1043 swap(l1._main, l2._main);
1044 swap(l1._bound, l2._bound);
1045 swap(l1._excerpt, l2._excerpt);
1046 }
1047
1048 //---------------------------------------------------------
1049 // PartChannelSettingsLink::applyProperty
1050 //---------------------------------------------------------
1051
applyProperty(Channel::Prop p,const Channel * from,Channel * to)1052 void PartChannelSettingsLink::applyProperty(Channel::Prop p, const Channel* from, Channel* to)
1053 {
1054 switch (p) {
1055 case Channel::Prop::VOLUME:
1056 to->setVolume(from->volume());
1057 break;
1058 case Channel::Prop::PAN:
1059 to->setPan(from->pan());
1060 break;
1061 case Channel::Prop::CHORUS:
1062 to->setChorus(from->chorus());
1063 break;
1064 case Channel::Prop::REVERB:
1065 to->setReverb(from->reverb());
1066 break;
1067 case Channel::Prop::NAME:
1068 to->setName(from->name());
1069 break;
1070 case Channel::Prop::DESCR:
1071 to->setDescr(from->descr());
1072 break;
1073 case Channel::Prop::PROGRAM:
1074 to->setProgram(from->program());
1075 break;
1076 case Channel::Prop::BANK:
1077 to->setBank(from->bank());
1078 break;
1079 case Channel::Prop::COLOR:
1080 to->setColor(from->color());
1081 break;
1082 case Channel::Prop::SOLOMUTE:
1083 to->setSoloMute(from->soloMute());
1084 break;
1085 case Channel::Prop::SOLO:
1086 to->setSolo(from->solo());
1087 break;
1088 case Channel::Prop::MUTE:
1089 to->setMute(from->mute());
1090 break;
1091 case Channel::Prop::SYNTI:
1092 to->setSynti(from->synti());
1093 break;
1094 case Channel::Prop::CHANNEL:
1095 to->setChannel(from->channel());
1096 break;
1097 case Channel::Prop::USER_BANK_CONTROL:
1098 to->setUserBankController(from->userBankController());
1099 break;
1100 };
1101 }
1102
1103 //---------------------------------------------------------
1104 // PartChannelSettingsLink::propertyChanged
1105 //---------------------------------------------------------
1106
propertyChanged(Channel::Prop p)1107 void PartChannelSettingsLink::propertyChanged(Channel::Prop p)
1108 {
1109 if (isExcerptProperty(p) == _excerpt)
1110 applyProperty(p, _main, _bound);
1111 }
1112
1113 //---------------------------------------------------------
1114 // channelIdx
1115 //---------------------------------------------------------
1116
channelIdx(const QString & s) const1117 int Instrument::channelIdx(const QString& s) const
1118 {
1119 int idx = 0;
1120 for (const Channel* a : _channel) {
1121 if (a->name().isEmpty() && s == Channel::DEFAULT_NAME)
1122 return idx;
1123 if (s == a->name())
1124 return idx;
1125 ++idx;
1126 }
1127 return -1;
1128 }
1129
1130 //---------------------------------------------------------
1131 // write
1132 //---------------------------------------------------------
1133
write(XmlWriter & xml) const1134 void MidiArticulation::write(XmlWriter& xml) const
1135 {
1136 if (name.isEmpty())
1137 xml.stag("Articulation");
1138 else
1139 xml.stag(QString("Articulation name=\"%1\"").arg(name));
1140 if (!descr.isEmpty())
1141 xml.tag("descr", descr);
1142 xml.tag("velocity", velocity);
1143 xml.tag("gateTime", gateTime);
1144 xml.etag();
1145 }
1146
1147 //---------------------------------------------------------
1148 // read
1149 //---------------------------------------------------------
1150
read(XmlReader & e)1151 void MidiArticulation::read(XmlReader& e)
1152 {
1153 name = e.attribute("name");
1154 while (e.readNextStartElement()) {
1155 const QStringRef& tag(e.name());
1156 if (tag == "velocity") {
1157 QString text(e.readElementText());
1158 if (text.endsWith("%"))
1159 text = text.left(text.size()-1);
1160 velocity = text.toInt();
1161 }
1162 else if (tag == "gateTime") {
1163 QString text(e.readElementText());
1164 if (text.endsWith("%"))
1165 text = text.left(text.size()-1);
1166 gateTime = text.toInt();
1167 }
1168 else if (tag == "descr")
1169 descr = e.readElementText();
1170 else
1171 e.unknown();
1172 }
1173 }
1174
1175 //---------------------------------------------------------
1176 // updateVelocity
1177 //---------------------------------------------------------
1178
updateVelocity(int * velocity,int,const QString & name)1179 void Instrument::updateVelocity(int* velocity, int /*channelIdx*/, const QString& name)
1180 {
1181 *velocity *= getVelocityMultiplier(name);
1182 }
1183
1184 //---------------------------------------------------------
1185 // updateVelocity
1186 //---------------------------------------------------------
1187
getVelocityMultiplier(const QString & name)1188 qreal Instrument::getVelocityMultiplier(const QString& name)
1189 {
1190 for (const MidiArticulation& a : qAsConst(_articulation)) {
1191 if (a.name == name) {
1192 return qreal(a.velocity) / 100;
1193 }
1194 }
1195 return 1;
1196 }
1197
1198 //---------------------------------------------------------
1199 // updateGateTime
1200 //---------------------------------------------------------
1201
updateGateTime(int * gateTime,int,const QString & name)1202 void Instrument::updateGateTime(int* gateTime, int /*channelIdx*/, const QString& name)
1203 {
1204 for (const MidiArticulation& a : qAsConst(_articulation)) {
1205 if (a.name == name) {
1206 *gateTime = a.gateTime;
1207 break;
1208 }
1209 }
1210 }
1211
1212
1213 //---------------------------------------------------------
1214 // updateGateTime
1215 //---------------------------------------------------------
1216
switchExpressive(MasterScore * score,Synthesizer * synth,bool expressive,bool force)1217 void Instrument::switchExpressive(MasterScore* score, Synthesizer* synth, bool expressive, bool force /* = false */)
1218 {
1219 // Only switch to expressive where necessary
1220 if (!synth || (expressive && !singleNoteDynamics()))
1221 return;
1222
1223 for (Channel* c : channel()) {
1224 c->switchExpressive(synth, expressive, force);
1225 if (score->playbackChannel(c))
1226 score->playbackChannel(c)->switchExpressive(synth, expressive, force);
1227 }
1228 }
1229
1230 //---------------------------------------------------------
1231 // operator==
1232 //---------------------------------------------------------
1233
operator ==(const Instrument & i) const1234 bool Instrument::operator==(const Instrument& i) const
1235 {
1236 int n = _longNames.size();
1237 if (i._longNames.size() != n)
1238 return false;
1239 for (int k = 0; k < n; ++k) {
1240 if (!(i._longNames[k] == _longNames[k]))
1241 return false;
1242 }
1243 n = _shortNames.size();
1244 if (i._shortNames.size() != n)
1245 return false;
1246 for (int k = 0; k < n; ++k) {
1247 if (!(i._shortNames[k] == _shortNames[k].name()))
1248 return false;
1249 }
1250 n = _channel.size();
1251 if (i._channel.size() != n)
1252 return false;
1253 for (int k = 0; k < n; ++k) {
1254 if (!(*i._channel[k] == *_channel[k]))
1255 return false;
1256 }
1257
1258 return i._minPitchA == _minPitchA
1259 && i._maxPitchA == _maxPitchA
1260 && i._minPitchP == _minPitchP
1261 && i._maxPitchP == _maxPitchP
1262 && i._useDrumset == _useDrumset
1263 && i._midiActions == _midiActions
1264 && i._articulation == _articulation
1265 && i._transpose.diatonic == _transpose.diatonic
1266 && i._transpose.chromatic == _transpose.chromatic
1267 && i._trackName == _trackName
1268 && *i.stringData() == *stringData()
1269 && i._singleNoteDynamics == _singleNoteDynamics;
1270 }
1271
1272 //---------------------------------------------------------
1273 // isDifferentInstrument
1274 /// Checks if the passed instrument is a different instrument.
1275 /// Does not compare channels.
1276 //---------------------------------------------------------
1277
isDifferentInstrument(const Instrument & i) const1278 bool Instrument::isDifferentInstrument(const Instrument& i) const
1279 {
1280 int n = _longNames.size();
1281 if (i._longNames.size() != n)
1282 return true;
1283 for (int k = 0; k < n; ++k) {
1284 if (!(i._longNames[k] == _longNames[k]))
1285 return true;
1286 }
1287 n = _shortNames.size();
1288 if (i._shortNames.size() != n)
1289 return true;
1290 for (int k = 0; k < n; ++k) {
1291 if (!(i._shortNames[k] == _shortNames[k].name()))
1292 return true;
1293 }
1294
1295 return i._minPitchA != _minPitchA
1296 || i._maxPitchA != _maxPitchA
1297 || i._minPitchP != _minPitchP
1298 || i._maxPitchP != _maxPitchP
1299 || i._useDrumset != _useDrumset
1300 || i._midiActions != _midiActions
1301 || i._articulation != _articulation
1302 || i._transpose.diatonic != _transpose.diatonic
1303 || i._transpose.chromatic != _transpose.chromatic
1304 || i._trackName != _trackName
1305 || !(*i.stringData() == *stringData())
1306 || i._singleNoteDynamics != _singleNoteDynamics;
1307 }
1308
1309 //---------------------------------------------------------
1310 // operator==
1311 //---------------------------------------------------------
1312
operator ==(const StaffName & i) const1313 bool StaffName::operator==(const StaffName& i) const
1314 {
1315 return (i._pos == _pos) && (i._name == _name);
1316 }
1317
toString() const1318 QString StaffName::toString() const
1319 {
1320 return _name;
1321 }
1322
1323 //---------------------------------------------------------
1324 // setUseDrumset
1325 //---------------------------------------------------------
1326
setUseDrumset(bool val)1327 void Instrument::setUseDrumset(bool val)
1328 {
1329 _useDrumset = val;
1330 if (val && !_drumset)
1331 _drumset = new Drumset(*smDrumset);
1332 }
1333
1334 //---------------------------------------------------------
1335 // setDrumset
1336 //---------------------------------------------------------
1337
setDrumset(const Drumset * ds)1338 void Instrument::setDrumset(const Drumset* ds)
1339 {
1340 delete _drumset;
1341 if (ds) {
1342 _useDrumset = true;
1343 _drumset = new Drumset(*ds);
1344 }
1345 else {
1346 _useDrumset = false;
1347 _drumset = 0;
1348 }
1349 }
1350
1351 //---------------------------------------------------------
1352 // setLongName
1353 // f is in richtext format
1354 //---------------------------------------------------------
1355
setLongName(const QString & f)1356 void Instrument::setLongName(const QString& f)
1357 {
1358 _longNames.clear();
1359 if (f.length() > 0)
1360 _longNames.append(StaffName(f, 0));
1361 }
1362
1363 //---------------------------------------------------------
1364 // setShortName
1365 // f is in richtext format
1366 //---------------------------------------------------------
1367
setShortName(const QString & f)1368 void Instrument::setShortName(const QString& f)
1369 {
1370 _shortNames.clear();
1371 if (f.length() > 0)
1372 _shortNames.append(StaffName(f, 0));
1373 }
1374
1375 //---------------------------------------------------------
1376 // addLongName
1377 //---------------------------------------------------------
1378
addLongName(const StaffName & f)1379 void Instrument::addLongName(const StaffName& f)
1380 {
1381 _longNames.append(f);
1382 }
1383
1384 //---------------------------------------------------------
1385 // addShortName
1386 //---------------------------------------------------------
1387
addShortName(const StaffName & f)1388 void Instrument::addShortName(const StaffName& f)
1389 {
1390 _shortNames.append(f);
1391 }
1392
1393 //---------------------------------------------------------
1394 // clefType
1395 //---------------------------------------------------------
1396
clefType(int staffIdx) const1397 ClefTypeList Instrument::clefType(int staffIdx) const
1398 {
1399 if (staffIdx >= _clefType.size()) {
1400 if (_clefType.empty())
1401 return ClefTypeList(staffIdx == 1 ? ClefType::F : ClefType::G);
1402 return _clefType[0];
1403 }
1404 return _clefType[staffIdx];
1405 }
1406
1407 //---------------------------------------------------------
1408 // setClefType
1409 //---------------------------------------------------------
1410
setClefType(int staffIdx,const ClefTypeList & c)1411 void Instrument::setClefType(int staffIdx, const ClefTypeList& c)
1412 {
1413 while (_clefType.size() <= staffIdx)
1414 _clefType.append(ClefTypeList());
1415 _clefType[staffIdx] = c;
1416 }
1417
1418 //---------------------------------------------------------
1419 // minPitchP
1420 //---------------------------------------------------------
1421
minPitchP() const1422 int Instrument::minPitchP() const
1423 {
1424 return _minPitchP;
1425 }
1426
1427 //---------------------------------------------------------
1428 // maxPitchP
1429 //---------------------------------------------------------
1430
maxPitchP() const1431 int Instrument::maxPitchP() const
1432 {
1433 return _maxPitchP;
1434 }
1435
1436 //---------------------------------------------------------
1437 // minPitchA
1438 //---------------------------------------------------------
1439
minPitchA() const1440 int Instrument::minPitchA() const
1441 {
1442 return _minPitchA;
1443 }
1444
1445 //---------------------------------------------------------
1446 // maxPitchA
1447 //---------------------------------------------------------
1448
maxPitchA() const1449 int Instrument::maxPitchA() const
1450 {
1451 return _maxPitchA;
1452 }
1453
1454 //---------------------------------------------------------
1455 // instrumentId
1456 //---------------------------------------------------------
1457
instrumentId() const1458 QString Instrument::instrumentId() const
1459 {
1460 return _instrumentId;
1461 }
1462
1463 //---------------------------------------------------------
1464 // instrument
1465 //---------------------------------------------------------
1466
instrument(int tick) const1467 const Instrument* InstrumentList::instrument(int tick) const
1468 {
1469 if (empty())
1470 return &defaultInstrument;
1471 auto i = upper_bound(tick);
1472 if (i == begin())
1473 return &defaultInstrument;
1474 --i;
1475 return i->second;
1476 }
1477
1478 //---------------------------------------------------------
1479 // instrument
1480 //---------------------------------------------------------
1481
instrument(int tick)1482 Instrument* InstrumentList::instrument(int tick)
1483 {
1484 if (empty())
1485 return &defaultInstrument;
1486 auto i = upper_bound(tick);
1487 if (i == begin())
1488 return &defaultInstrument;
1489 --i;
1490 return i->second;
1491 }
1492
1493 //---------------------------------------------------------
1494 // setInstrument
1495 //---------------------------------------------------------
1496
setInstrument(Instrument * instr,int tick)1497 void InstrumentList::setInstrument(Instrument* instr, int tick)
1498 {
1499 if (!insert({tick, instr}).second)
1500 (*this)[tick] = instr;
1501 }
1502
1503 //---------------------------------------------------------
1504 // longName
1505 //---------------------------------------------------------
1506
longNames() const1507 const QList<StaffName>& Instrument::longNames() const
1508 {
1509 return _longNames;
1510 }
1511
1512 //---------------------------------------------------------
1513 // shortName
1514 //---------------------------------------------------------
1515
shortNames() const1516 const QList<StaffName>& Instrument::shortNames() const
1517 {
1518 return _shortNames;
1519 }
1520
1521 //---------------------------------------------------------
1522 // longName
1523 //---------------------------------------------------------
1524
longNames()1525 QList<StaffName>& Instrument::longNames()
1526 {
1527 return _longNames;
1528 }
1529
1530 //---------------------------------------------------------
1531 // shortName
1532 //---------------------------------------------------------
1533
shortNames()1534 QList<StaffName>& Instrument::shortNames()
1535 {
1536 return _shortNames;
1537 }
1538
1539 //---------------------------------------------------------
1540 // trackName
1541 //---------------------------------------------------------
1542
trackName() const1543 QString Instrument::trackName() const
1544 {
1545 return _trackName;
1546 }
1547
setTrackName(const QString & s)1548 void Instrument::setTrackName(const QString& s)
1549 {
1550 _trackName = s;
1551 }
1552
1553 //---------------------------------------------------------
1554 // fromTemplate
1555 //---------------------------------------------------------
1556
fromTemplate(const InstrumentTemplate * t)1557 Instrument Instrument::fromTemplate(const InstrumentTemplate* t)
1558 {
1559 Instrument instr(t->id);
1560 instr.setAmateurPitchRange(t->minPitchA, t->maxPitchA);
1561 instr.setProfessionalPitchRange(t->minPitchP, t->maxPitchP);
1562 for (const StaffName &sn : t->longNames)
1563 instr.addLongName(StaffName(sn.name(), sn.pos()));
1564 for (const StaffName &sn : t->shortNames)
1565 instr.addShortName(StaffName(sn.name(), sn.pos()));
1566 instr.setTrackName(t->trackName);
1567 instr.setTranspose(t->transpose);
1568 instr.setInstrumentId(t->musicXMLid);
1569 if (t->useDrumset)
1570 instr.setDrumset(t->drumset ? t->drumset : smDrumset);
1571 for (int i = 0; i < t->nstaves(); ++i)
1572 instr.setClefType(i, t->clefTypes[i]);
1573 instr.setMidiActions(t->midiActions);
1574 instr.setArticulation(t->articulation);
1575 instr._channel.clear();
1576 for (const Channel& c : t->channel)
1577 instr._channel.append(new Channel(c));
1578 instr.setStringData(t->stringData);
1579 instr.setSingleNoteDynamics(t->singleNoteDynamics);
1580 return instr;
1581 }
1582
1583 //---------------------------------------------------------
1584 // updateInstrumentId
1585 //---------------------------------------------------------
1586
updateInstrumentId()1587 void Instrument::updateInstrumentId()
1588 {
1589 if (!_id.isEmpty() || _instrumentId.isEmpty())
1590 return;
1591
1592 // When reading a score create with pre-3.6, instruments doesn't
1593 // have an id define in the instrument. So try to find the instrumentId
1594 // based on MusicXMLid.
1595 // This requires a hack for instruments using MusicXMLid "strings.group"
1596 // because there are multiple instrument using this same id.
1597 // For these instruments, use the value of controller 32 of the "arco"
1598 // channel to find the correct instrument.
1599 const QString arco = QString("arco");
1600 const bool groupHack = instrumentId() == QString("strings.group");
1601 const int idxref = channelIdx(arco);
1602 const int val32ref = (idxref < 0) ? -1 : channel(idxref)->bank();
1603 QString fallback;
1604
1605 for (InstrumentGroup* g : instrumentGroups) {
1606 for (InstrumentTemplate* it : g->instrumentTemplates) {
1607 if (it->musicXMLid == instrumentId()) {
1608 if (groupHack) {
1609 if (fallback.isEmpty())
1610 // Instrument "Strings" doesn't have bank defined so
1611 // if no "strings.group" instrument with requested bank
1612 // is found, assume "Strings".
1613 fallback = it->id;
1614 for (const Channel& chan : it->channel) {
1615 if ((chan.name() == arco) && (chan.bank() == val32ref)) {
1616 _id = it->id;
1617 return;
1618 }
1619 }
1620 }
1621 else {
1622 _id = it->id;
1623 return;
1624 }
1625 }
1626 }
1627 }
1628
1629 _id = fallback.isEmpty() ? QString("piano") : fallback;
1630 }
1631
1632 //---------------------------------------------------------
1633 // Instrument::playbackChannel
1634 //---------------------------------------------------------
1635
playbackChannel(int idx,const MasterScore * score) const1636 const Channel* Instrument::playbackChannel(int idx, const MasterScore* score) const
1637 {
1638 return score->playbackChannel(channel(idx));
1639 }
1640
1641
1642 //---------------------------------------------------------
1643 // Instrument::playbackChannel
1644 //---------------------------------------------------------
1645
playbackChannel(int idx,MasterScore * score)1646 Channel* Instrument::playbackChannel(int idx, MasterScore* score)
1647 {
1648 return score->playbackChannel(channel(idx));
1649 }
1650
1651 //---------------------------------------------------------
1652 // getSingleNoteDynamicsFromTemplate
1653 //---------------------------------------------------------
1654
getSingleNoteDynamicsFromTemplate() const1655 bool Instrument::getSingleNoteDynamicsFromTemplate() const
1656 {
1657 QString templateName = trackName().toLower().replace(" ", "-").replace("♭", "b");
1658 InstrumentTemplate* tp = searchTemplate(templateName);
1659 if (tp)
1660 return tp->singleNoteDynamics;
1661 return true;
1662 }
1663
1664 //---------------------------------------------------------
1665 // setSingleNoteDynamicsFromTemplate
1666 //---------------------------------------------------------
1667
setSingleNoteDynamicsFromTemplate()1668 void Instrument::setSingleNoteDynamicsFromTemplate()
1669 {
1670 setSingleNoteDynamics(getSingleNoteDynamicsFromTemplate());
1671 }
1672
1673 //---------------------------------------------------------
1674 // StaffNameList::write
1675 //---------------------------------------------------------
1676
write(XmlWriter & xml,const char * name) const1677 void StaffNameList::write(XmlWriter& xml, const char* name) const
1678 {
1679 for (const StaffName& sn : *this)
1680 sn.write(xml, name);
1681 }
1682
toStringList() const1683 QStringList StaffNameList::toStringList() const
1684 {
1685 QStringList result;
1686
1687 for (const StaffName& name : *this)
1688 result << name.toString();
1689
1690 return result;
1691 }
1692 }
1693
1694