Skip to content

Commit

Permalink
Move playback channels to MidiMapping, fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
dmitrio95 committed Feb 11, 2019
1 parent 568176a commit 830f989
Show file tree
Hide file tree
Showing 14 changed files with 186 additions and 176 deletions.
19 changes: 6 additions & 13 deletions libmscore/instrument.cpp
Expand Up @@ -641,8 +641,8 @@ void Channel::write(XmlWriter& xml, const Part* part) const
if (_solo)
xml.tag("solo", _solo);
if (part && part->masterScore()->exportMidiMapping() && part->score() == part->masterScore()) {
xml.tag("midiPort", part->masterScore()->midiMapping(_channel)->port);
xml.tag("midiChannel", part->masterScore()->midiMapping(_channel)->channel);
xml.tag("midiPort", part->masterScore()->midiMapping(_channel)->port());
xml.tag("midiChannel", part->masterScore()->midiMapping(_channel)->channel());
}
for (const NamedEventList& a : midiActions)
a.write(xml, "MidiAction");
Expand Down Expand Up @@ -728,20 +728,13 @@ void Channel::read(XmlReader& e, Part* part)
_solo = e.readInt();
else if (tag == "midiPort") {
int midiPort = e.readInt();
if (part) {
MidiMapping mm;
mm.port = midiPort;
mm.channel = -1;
mm.part = part;
mm.articulation = this;
part->masterScore()->midiMapping()->append(mm);
_channel = part->masterScore()->midiMapping()->size() - 1;
}
if (part && part->score()->isMaster())
part->masterScore()->addMidiMapping(this, part, midiPort, -1);
}
else if (tag == "midiChannel") {
int midiChannel = e.readInt();
if (part)
part->masterScore()->midiMapping(_channel)->channel = midiChannel;
if (part && part->score()->isMaster())
part->masterScore()->updateMidiMapping(this, part, -1, midiChannel);
}
else
e.unknown();
Expand Down
1 change: 1 addition & 0 deletions libmscore/instrument.h
Expand Up @@ -222,6 +222,7 @@ class PartChannelSettingsLink final : private ChannelListener {
void propertyChanged(Channel::Prop p) override;

public:
PartChannelSettingsLink() : _main(nullptr), _bound(nullptr), _excerpt(false) {}
PartChannelSettingsLink(Channel* main, Channel* bound, bool excerpt);
PartChannelSettingsLink(const PartChannelSettingsLink&) = delete;
PartChannelSettingsLink(PartChannelSettingsLink&&);
Expand Down
156 changes: 90 additions & 66 deletions libmscore/midimapping.cpp
Expand Up @@ -60,12 +60,12 @@ void MasterScore::checkMidiMapping()
int lastChannel = -1; // port*16+channel
int lastDrumPort = -1;
int index = 0;
for (MidiMapping m : _midiMapping) {
for (const MidiMapping& m : _midiMapping) {
if (index >= drum.size())
break;
if (drum[index]) {
lastDrumPort++;
if (m.port != lastDrumPort) {
if (m.port() != lastDrumPort) {
isSimpleMidiMaping = false;
return;
}
Expand All @@ -76,7 +76,7 @@ void MasterScore::checkMidiMapping()
lastChannel++;
int p = lastChannel / 16;
int c = lastChannel % 16;
if (m.port != p || m.channel != c) {
if (m.port() != p || m.channel() != c) {
isSimpleMidiMaping = false;
return;
}
Expand Down Expand Up @@ -163,47 +163,27 @@ void MasterScore::rebuildExcerptsMidiMapping()
}
}

//---------------------------------------------------------
// rebuildPlaybackChannels
//---------------------------------------------------------

void MasterScore::rebuildPlaybackChannels()
{
_playbackCommonSettingsLinks.clear();
_playbackChannels.clear();
for (const Part* part : parts()) {
for (const auto& i : *part->instruments()) {
const Instrument* instr = i.second;
for (Channel* channel : instr->channel()) {
Channel* playbackChannel = new Channel(*channel);
_playbackChannels.emplace_back(playbackChannel);
_playbackCommonSettingsLinks.emplace_back(playbackChannel, channel, /* excerpt */ false);
_midiMapping[playbackChannel->channel()].articulation = playbackChannel;
}
}
}
}

//---------------------------------------------------------
// reorderMidiMapping
// Set mappings in order you see in Add->Instruments
//---------------------------------------------------------

void MasterScore::reorderMidiMapping()
{
using std::swap;
int sequenceNumber = 0;
for (Part* part : parts()) {
const InstrumentList* il = part->instruments();
for (auto i = il->begin(); i != il->end(); ++i) {
const Instrument* instr = i->second;
for (Channel* channel : instr->channel()) {
if (!(_midiMapping[sequenceNumber].part == part
&& _midiMapping[sequenceNumber].articulation == channel)) {
if (!(_midiMapping[sequenceNumber].part() == part
&& _midiMapping[sequenceNumber].masterChannel == channel)) {
int shouldBe = channel->channel();
_midiMapping.swap(sequenceNumber, shouldBe);
_midiMapping[sequenceNumber].articulation->setChannel(sequenceNumber);
swap(_midiMapping[sequenceNumber], _midiMapping[shouldBe]);
_midiMapping[sequenceNumber].articulation()->setChannel(sequenceNumber);
channel->setChannel(sequenceNumber);
_midiMapping[shouldBe].articulation->setChannel(shouldBe);
_midiMapping[shouldBe].articulation()->setChannel(shouldBe);
}
sequenceNumber++;
}
Expand All @@ -221,7 +201,7 @@ void MasterScore::removeDeletedMidiMapping()
int removeOffset = 0;
int mappingSize = _midiMapping.size();
for (int index = 0; index < mappingSize; index++) {
Part* p = midiMapping(index)->part;
Part* p = midiMapping(index)->part();
if (!parts().contains(p)) {
removeOffset++;
continue;
Expand All @@ -231,9 +211,9 @@ void MasterScore::removeDeletedMidiMapping()
const InstrumentList* il = p->instruments();
for (auto i = il->begin(); i != il->end() && !channelExists; ++i) {
const Instrument* instr = i->second;
channelExists = (_midiMapping[index].articulation->channel() != -1
&& instr->channel().contains(_midiMapping[index].articulation)
&& !(_midiMapping[index].port == -1 && _midiMapping[index].channel == -1));
channelExists = (_midiMapping[index].articulation()->channel() != -1
&& instr->channel().contains(_midiMapping[index].masterChannel)
&& !(_midiMapping[index].port() == -1 && _midiMapping[index].channel() == -1));
if (channelExists)
break;
}
Expand All @@ -243,15 +223,15 @@ void MasterScore::removeDeletedMidiMapping()
}
// Let's do a left shift by 'removeOffset' items if necessary
if (index != 0 && removeOffset != 0) {
_midiMapping[index-removeOffset] = _midiMapping[index];
_midiMapping[index-removeOffset] = std::move(_midiMapping[index]);

int chanVal = _midiMapping[index-removeOffset].articulation->channel();
_midiMapping[index-removeOffset].articulation->setChannel(chanVal - removeOffset);
const int chanVal = _midiMapping[index-removeOffset].articulation()->channel();
_midiMapping[index-removeOffset].articulation()->setChannel(chanVal - removeOffset);
}
}
// We have 'removeOffset' deleted instruments, let's remove their mappings
for (int index = 0; index < removeOffset; index++)
_midiMapping.removeLast();
_midiMapping.pop_back();
}

//---------------------------------------------------------
Expand All @@ -266,12 +246,12 @@ int MasterScore::updateMidiMapping()
searchMidiMappingFrom = 0;
occupiedMidiChannels.reserve(_midiMapping.size()); // Bringing down the complexity of insertion to amortized O(1)

for(MidiMapping mm :_midiMapping) {
if (mm.port == -1 || mm.channel == -1)
for (const MidiMapping& mm :_midiMapping) {
if (mm.port() == -1 || mm.channel() == -1)
continue;
occupiedMidiChannels.insert((int)(mm.port)*16+(int)mm.channel);
if (maxport < mm.port)
maxport = mm.port;
occupiedMidiChannels.insert((int)(mm.port())*16+(int)mm.channel());
if (maxport < mm.port())
maxport = mm.port();
}

for (Part* part : parts()) {
Expand All @@ -281,56 +261,100 @@ int MasterScore::updateMidiMapping()
bool drum = instr->useDrumset();
for (Channel* channel : instr->channel()) {
bool channelExists = false;
for (MidiMapping mapping: _midiMapping) {
if (channel == mapping.articulation && channel->channel() != -1) {
for (const MidiMapping& mapping: _midiMapping) {
if (channel == mapping.masterChannel && channel->channel() != -1) {
channelExists = true;
break;
}
}
// Channel could already exist, but have unassigned port or channel. Repair and continue
if (channelExists) {
if (_midiMapping[channel->channel()].port == -1) {
int nm = getNextFreeMidiMapping(-1, _midiMapping[channel->channel()].channel);
_midiMapping[channel->channel()].port = nm / 16;
if (_midiMapping[channel->channel()].port() == -1) {
const int nm = getNextFreeMidiMapping(-1, _midiMapping[channel->channel()].channel());
_midiMapping[channel->channel()]._port = nm / 16;
}
else if (_midiMapping[channel->channel()].channel == -1) {
else if (_midiMapping[channel->channel()].channel() == -1) {
if (drum) {
_midiMapping[channel->channel()].port = getNextFreeDrumMidiMapping() / 16;
_midiMapping[channel->channel()].channel = 9;
_midiMapping[channel->channel()]._port = getNextFreeDrumMidiMapping() / 16;
_midiMapping[channel->channel()]._channel = 9;
continue;
}
int nm = getNextFreeMidiMapping(_midiMapping[channel->channel()].port);
_midiMapping[channel->channel()].port = nm / 16;
_midiMapping[channel->channel()].channel = nm % 16;
int nm = getNextFreeMidiMapping(_midiMapping[channel->channel()].port());
_midiMapping[channel->channel()]._port = nm / 16;
_midiMapping[channel->channel()]._channel = nm % 16;
}
continue;
}

MidiMapping mm;
int midiPort;
int midiChannel;
if (drum) {
mm.port = getNextFreeDrumMidiMapping() / 16;
mm.channel = 9;
midiPort = getNextFreeDrumMidiMapping() / 16;
midiChannel = 9;
}
else {
int nm = getNextFreeMidiMapping();
mm.port = nm / 16;
mm.channel = nm % 16;
midiPort = nm / 16;
midiChannel = nm % 16;
}

if (mm.port > maxport)
maxport = mm.port;
if (midiPort > maxport)
maxport = midiPort;

mm.part = part;
// mm.articulation = channel; // now set in rebuildPlaybackChannels()

_midiMapping.append(mm);
channel->setChannel(_midiMapping.size() - 1);
addMidiMapping(channel, part, midiPort, midiChannel);
}
}
}
rebuildPlaybackChannels();
return maxport;
}

//---------------------------------------------------------
// addMidiMapping
//---------------------------------------------------------

void MasterScore::addMidiMapping(Channel* channel, Part* part, int midiPort, int midiChannel)
{
if (!part->score()->isMaster())
return;

MidiMapping mm;
mm._part = part;
mm.masterChannel = channel;
mm._articulation.reset(new Channel(*channel));
mm.link = PartChannelSettingsLink(mm.articulation(), mm.masterChannel, /* excerpt */ false);

mm._port = midiPort;
mm._channel = midiChannel;

const int mscoreChannel = _midiMapping.size();
mm._articulation->setChannel(mscoreChannel);
mm.masterChannel->setChannel(mscoreChannel);

_midiMapping.push_back(std::move(mm));
}

//---------------------------------------------------------
// updateMidiMapping
//---------------------------------------------------------

void MasterScore::updateMidiMapping(Channel* channel, Part* part, int midiPort, int midiChannel)
{
const int c = channel->channel();
if (c < 0)
return;
if (c >= int(masterScore()->midiMapping().size())) {
qDebug("Can't set midi channel: midiMapping is empty!");
return;
}
MidiMapping& mm = _midiMapping[c];

if (midiChannel != -1)
mm._channel = midiChannel;
if (midiPort != -1)
mm._port = midiPort;
if (part)
mm._part = part->masterPart();
}

} // namespace Ms

31 changes: 4 additions & 27 deletions libmscore/part.cpp
Expand Up @@ -276,33 +276,10 @@ int Part::midiPort() const
void Part::setMidiChannel(int ch, int port, int tick)
{
Channel* channel = instrument(tick)->channel(0);
if (channel->channel() == -1) {
// Add new mapping
MidiMapping mm;
mm.part = this;
mm.articulation = channel;
mm.channel = -1;
mm.port = -1;
if (ch != -1)
mm.channel = ch;
if (port != -1)
mm.port = port;
channel->setChannel(masterScore()->midiMapping()->size());
masterScore()->midiMapping()->append(mm);
}
else {
// Update existing mapping
if (channel->channel() >= masterScore()->midiMapping()->size()) {
qDebug()<<"Can't' set midi channel: midiMapping is empty!";
return;
}

if (ch != -1)
masterScore()->midiMapping(channel->channel())->channel = ch;
if (port != -1)
masterScore()->midiMapping(channel->channel())->port = port;
masterScore()->midiMapping(channel->channel())->part = this;
}
if (channel->channel() == -1)
masterScore()->addMidiMapping(channel, this, port, ch);
else
masterScore()->updateMidiMapping(channel, this, port, ch);
}

//---------------------------------------------------------
Expand Down
14 changes: 7 additions & 7 deletions libmscore/score.cpp
Expand Up @@ -3719,13 +3719,13 @@ ChordRest* Score::findCRinStaff(int tick, int staffIdx) const

void MasterScore::setSoloMute()
{
for (int i = 0; i < _midiMapping.size(); i++) {
Channel* b = _midiMapping[i].articulation;
for (unsigned i = 0; i < _midiMapping.size(); i++) {
Channel* b = _midiMapping[i].articulation();
if (b->solo()) {
b->setSoloMute(false);
for (int j = 0; j < _midiMapping.size(); j++) {
Channel* a = _midiMapping[j].articulation;
bool sameMidiMapping = _midiMapping[i].port == _midiMapping[j].port && _midiMapping[i].channel == _midiMapping[j].channel;
for (unsigned j = 0; j < _midiMapping.size(); j++) {
Channel* a = _midiMapping[j].articulation();
bool sameMidiMapping = _midiMapping[i].port() == _midiMapping[j].port() && _midiMapping[i].channel() == _midiMapping[j].channel();
a->setSoloMute((i != j && !a->solo() && !sameMidiMapping));
a->setSolo(i == j || a->solo() || sameMidiMapping);
}
Expand Down Expand Up @@ -4458,8 +4458,8 @@ void MasterScore::setPlaybackScore(Score* score)
if (!_playbackScore)
return;

for (auto& ch : _playbackChannels)
ch->setSoloMute(true);
for (MidiMapping& mm : _midiMapping)
mm.articulation()->setSoloMute(true);
for (Part* part : score->parts()) {
for (auto& i : *part->instruments()) {
Instrument* instr = i.second;
Expand Down

0 comments on commit 830f989

Please sign in to comment.