Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assigning channels #1083

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions libmscore/instrchange.cpp
Expand Up @@ -40,9 +40,9 @@ void InstrumentChange::write(Xml& xml) const
{
xml.stag("InstrumentChange");
if (segment())
staff()->part()->instr(segment()->tick())->write(xml); // _instrument may not reflect mixer changes
staff()->part()->instr(segment()->tick())->write(xml, staff() ? staff()->part() : 0); // _instrument may not reflect mixer changes
else
_instrument.write(xml);
_instrument.write(xml, staff() ? staff()->part() : 0);
Text::writeProperties(xml);
xml.etag();
}
Expand All @@ -56,7 +56,7 @@ void InstrumentChange::read(XmlReader& e)
while (e.readNextStartElement()) {
const QStringRef& tag(e.name());
if (tag == "Instrument")
_instrument.read(e);
_instrument.read(e, staff() ? staff()->part() : 0, true);
else if (!Text::readProperties(e))
e.unknown();
}
Expand Down
2 changes: 2 additions & 0 deletions libmscore/instrchange.h
Expand Up @@ -36,6 +36,8 @@ class InstrumentChange : public Text {

Instrument instrument() const { return _instrument; }
void setInstrument(const Instrument& i) { _instrument = i; }
void setChannelNum(int i, int ch) { _instrument.channel(i).channel = ch; }
void setChannel(int k, const Channel& ch) { _instrument.setChannel(k, ch); }
Segment* segment() const { return (Segment*)parent(); }
};

Expand Down
4 changes: 2 additions & 2 deletions libmscore/instrtemplate.cpp
Expand Up @@ -280,7 +280,7 @@ void InstrumentTemplate::write(Xml& xml) const
foreach(const NamedEventList& a, midiActions)
a.write(xml, "MidiAction");
foreach(const Channel& a, channel)
a.write(xml);
a.write(xml, 0);
foreach(const MidiArticulation& ma, articulation) {
bool isGlobal = false;
foreach(const MidiArticulation& ga, Ms::articulation) {
Expand Down Expand Up @@ -437,7 +437,7 @@ void InstrumentTemplate::read(XmlReader& e)
}
else if (tag == "Channel" || tag == "channel") {
Channel a;
a.read(e);
a.read(e, 0);
channel.append(a);
}
else if (tag == "Articulation") {
Expand Down
77 changes: 67 additions & 10 deletions libmscore/instrument.cpp
Expand Up @@ -18,6 +18,7 @@
#include "stringdata.h"
#include "instrtemplate.h"
#include "mscore.h"
#include "score.h"

namespace Ms {

Expand Down Expand Up @@ -152,7 +153,7 @@ void StaffName::read(XmlReader& e)
// InstrumentData::write
//---------------------------------------------------------

void InstrumentData::write(Xml& xml) const
void InstrumentData::write(Xml& xml, Part* part) const
{
xml.stag("Instrument");
foreach(const StaffName& doc, _longNames)
Expand Down Expand Up @@ -209,15 +210,15 @@ void InstrumentData::write(Xml& xml) const
foreach(const MidiArticulation& a, _articulation)
a.write(xml);
foreach(const Channel& a, _channel)
a.write(xml);
a.write(xml, part);
xml.etag();
}

//---------------------------------------------------------
// InstrumentData::read
//---------------------------------------------------------

void InstrumentData::read(XmlReader& e)
void InstrumentData::read(XmlReader& e, Part* part, bool fromInstrChange)
{
int program = -1;
int bank = 0;
Expand Down Expand Up @@ -300,8 +301,10 @@ void InstrumentData::read(XmlReader& e)
}
else if (tag == "Channel" || tag == "channel") {
Channel a;
a.read(e);
a.read(e, part, fromInstrChange, _channel.size());
_channel.append(a);
if (part != 0 && a.channel != -1 && a.channel < part->score()->midiMapping()->size() && part->score()->midiMapping(a.channel)->articulation == 0)
part->score()->midiMapping(a.channel)->articulation = &_channel[_channel.size() - 1];
}
else if (tag == "clef") { // sets both transposing and concert clef
int idx = e.intAttribute("staff", 1) - 1;
Expand Down Expand Up @@ -344,6 +347,7 @@ void InstrumentData::read(XmlReader& e)
a.bank = bank;
a.volume = volume;
a.pan = pan;
a.channel = -1;
_channel.append(a);
}
if (_useDrumset != DrumsetKind::NONE) {
Expand Down Expand Up @@ -399,7 +403,7 @@ Channel::Channel()
// write
//---------------------------------------------------------

void Channel::write(Xml& xml) const
void Channel::write(Xml& xml, Part* part) const
{
if (name.isEmpty() || name == "normal")
xml.stag("Channel");
Expand Down Expand Up @@ -435,6 +439,10 @@ void Channel::write(Xml& xml) const
xml.tag("mute", mute);
if (solo)
xml.tag("solo", solo);
if (part != 0 && part->score()->exportMidiMapping()) {
xml.tag("midiPort", part->score()->midiMapping(channel)->port);
xml.tag("midiChannel", part->score()->midiMapping(channel)->channel);
}
foreach(const NamedEventList& a, midiActions)
a.write(xml, "MidiAction");
foreach(const MidiArticulation& a, articulation)
Expand All @@ -446,7 +454,7 @@ void Channel::write(Xml& xml) const
// read
//---------------------------------------------------------

void Channel::read(XmlReader& e)
void Channel::read(XmlReader& e, Part* part, bool fromInstrChange, int channelN)
{
// synti = 0;
name = e.attribute("name");
Expand Down Expand Up @@ -514,6 +522,55 @@ void Channel::read(XmlReader& e)
mute = e.readInt();
else if (tag == "solo")
solo = e.readInt();
else if (tag == "midiPort") {
int midiPort = e.readInt();
if (part != 0) {
if (!fromInstrChange) {
MidiMapping mm;
mm.port = -1;
mm.channel = -1;
mm.part = part;
mm.articulation = 0; // Assign articulation after return
part->score()->midiMapping()->append(mm);
channel = part->score()->midiMapping()->size() - 1;
part->score()->midiMapping(channel)->port = midiPort;
}
else {
// Reading instrument from Instrument Change element
// Checking if we already have instruments with this program
Instrument* first = 0;
InstrumentList* ll = part->instrList();
for (auto instr = ll->begin(); instr != ll->end() && first == 0; instr++) {
for (int _k = 0; _k < instr->second.channel().size() && first == 0; _k++) {
if (instr->second.channel(_k).program == program && instr->second.channel(_k).channel != -1)
first = &(instr->second);
}
}
// This instrument is not unique, there are already instruments with the same
// midi program.
if (first) {
if (channelN < first->channel().size())
channel = first->channel(channelN).channel;
}
else {
// Create a new channel and midi mapping
MidiMapping mm;
mm.port = -1;
mm.channel = -1;
mm.part = part;
mm.articulation = 0; // Assign articulation after return
part->score()->midiMapping()->append(mm);
channel = part->score()->midiMapping()->size() - 1;
part->score()->midiMapping(channel)->port = midiPort;
}
}
}
}
else if (tag == "midiChannel") {
if (part != 0)
part->score()->midiMapping(channel)->channel = e.readInt();
}

else
e.unknown();
}
Expand Down Expand Up @@ -827,18 +884,18 @@ bool Instrument::operator==(const Instrument& s) const
// read
//---------------------------------------------------------

void Instrument::read(XmlReader& e)
void Instrument::read(XmlReader& e, Part* part, bool fromInstrChange)
{
d->read(e);
d->read(e, part, fromInstrChange);
}

//---------------------------------------------------------
// write
//---------------------------------------------------------

void Instrument::write(Xml& xml) const
void Instrument::write(Xml& xml, Part* part) const
{
d->write(xml);
d->write(xml, part);
}

//---------------------------------------------------------
Expand Down
9 changes: 5 additions & 4 deletions libmscore/instrument.h
Expand Up @@ -25,6 +25,7 @@ class Xml;
class XmlReader;
class Drumset;
class StringData;
class Part;

//---------------------------------------------------------
// StaffName
Expand Down Expand Up @@ -105,8 +106,8 @@ struct Channel {
QList<MidiArticulation> articulation;

Channel();
void write(Xml&) const;
void read(XmlReader&);
void write(Xml&, Part* part) const;
void read(XmlReader&, Part* part, bool fromInstrChange = false, int channelN = 0);
void updateInitList() const;
bool operator==(const Channel& c) { return (name == c.name) && (channel == c.channel); }
};
Expand All @@ -129,8 +130,8 @@ class Instrument {
Instrument& operator=(const Instrument&);
bool operator==(const Instrument&) const;

void read(XmlReader&);
void write(Xml& xml) const;
void read(XmlReader&, Part* part, bool fromInstrChange = false);
void write(Xml& xml, Part* part) const;
NamedEventList* midiAction(const QString& s, int channel) const;
int channelIdx(const QString& s) const;
void updateVelocity(int* velocity, int channel, const QString& name);
Expand Down
5 changes: 3 additions & 2 deletions libmscore/instrument_p.h
Expand Up @@ -15,6 +15,7 @@

#include "instrument.h"
#include "stringdata.h"
#include "part.h"

namespace Ms {

Expand Down Expand Up @@ -44,8 +45,8 @@ class InstrumentData : public QSharedData {
InstrumentData(const InstrumentData&);
~InstrumentData();

void read(XmlReader&);
void write(Xml& xml) const;
void read(XmlReader&, Ms::Part* part, bool fromInstrChange);
void write(Xml& xml, Part* part) const;
NamedEventList* midiAction(const QString& s, int channel) const;
int channelIdx(const QString& s) const;
void updateVelocity(int* velocity, int channel, const QString& name);
Expand Down
2 changes: 2 additions & 0 deletions libmscore/mscore.h
Expand Up @@ -64,6 +64,8 @@ static const qreal SPATIUM20 = 5.0 / PPI; // size of Spatium for 20pt font in in
static const int MAX_STAVES = 4;
#define MMSP(x) Spatium((x) * .1)

static const int MAX_MIDI_PORT = 99; // Midi ports available: 1..99

static const char mimeSymbolFormat[] = "application/mscore/symbol";
static const char mimeSymbolListFormat[] = "application/mscore/symbollist";
static const char mimeStaffListFormat[] = "application/mscore/stafflist";
Expand Down
69 changes: 64 additions & 5 deletions libmscore/part.cpp
Expand Up @@ -18,6 +18,7 @@
#include "note.h"
#include "drumset.h"
#include "instrtemplate.h"
#include "instrchange.h"
#include "text.h"
#include "measure.h"
#include "stringdata.h"
Expand Down Expand Up @@ -73,7 +74,7 @@ void Part::read(XmlReader& e)
staff->read(e);
}
else if (tag == "Instrument")
instr(0)->read(e);
instr(0)->read(e, this);
else if (tag == "name")
instr(0)->setLongName(e.readElementText());
else if (tag == "shortName")
Expand Down Expand Up @@ -101,7 +102,7 @@ void Part::write(Xml& xml) const
if (!_show)
xml.tag("show", _show);
xml.tag("trackName", _partName);
instr(0)->write(xml);
instr(0)->write(xml, const_cast<Part*>(this)); // Safe. We do not write anything to it
xml.etag();
}

Expand Down Expand Up @@ -238,12 +239,55 @@ int Part::midiChannel() const
}

//---------------------------------------------------------
// setMidiChannel
// called from importmusicxml
// midiPort
//---------------------------------------------------------

void Part::setMidiChannel(int) const
int Part::midiPort() const
{
return score()->midiPort(instr(0)->channel(0).channel);
}

//---------------------------------------------------------
// setMidiChannel
// called from importmusicxml, importmidi
// Usage:
// setMidiChannel(channel) to set channel
// setMidiChannel(-1, port) to set port
// setMidiChannel(channel, port) to set both
//---------------------------------------------------------

void Part::setMidiChannel(int ch, int port)
{
// If there is a new added element in instr(0)->channel(), it's channel == -1
// Adding information about Channel to midiMapping
if (instr(0)->channel(0).channel == -1) {
Channel* a = &(instr(0)->channel(0));
MidiMapping mm;
mm.part = this;
mm.articulation = a;
mm.channel = 0;
mm.port = 0;
if (ch != -1)
mm.channel = ch;
if (port != -1)
mm.port = port;
a->channel = score()->midiMapping()->size();
score()->midiMapping()->append(mm);
}
else {
// Or just updating
if (score()->midiMapping()->size() == 0) {
if (MScore::debugMode)
qFatal("Can't' set midi channel: midiMapping is empty!");
else
return;
}
if (ch != -1)
score()->midiMapping(instr(0)->channel(0).channel)->channel = ch;
if (port != -1)
score()->midiMapping(instr(0)->channel(0).channel)->port = port;
score()->midiMapping(instr(0)->channel(0).channel)->part = this;
}
}

//---------------------------------------------------------
Expand Down Expand Up @@ -378,5 +422,20 @@ int Part::endTrack() const
return _staves.back()->idx() * VOICES + VOICES;
}

//---------------------------------------------------------
// getInstrumentChangeByTick
//---------------------------------------------------------

InstrumentChange* Part::getInstrumentChangeByTick(int tick)
{
Segment* s = score()->tick2segmentMM(tick, true, Segment::Type::ChordRest);
if (s) {
foreach(Element* e1, s->annotations()) {
if (e1->type() == Element::Type::INSTRUMENT_CHANGE)
return static_cast<InstrumentChange*>(e1);
}
}
return 0;
}
}