summaryrefslogtreecommitdiff
path: root/muse2/muse/track.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'muse2/muse/track.cpp')
-rw-r--r--muse2/muse/track.cpp226
1 files changed, 221 insertions, 5 deletions
diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp
index 2a57a4e3..cdb81a8f 100644
--- a/muse2/muse/track.cpp
+++ b/muse2/muse/track.cpp
@@ -33,6 +33,9 @@
#include "audio.h"
#include "globaldefs.h"
#include "route.h"
+#include "drummap.h"
+#include "midictrl.h"
+#include "helper.h"
namespace MusECore {
@@ -45,8 +48,8 @@ bool Track::_tmpSoloChainNoDec = false;
//int Track::_tmpIsAuxProcRefCount = 0;
const char* Track::_cname[] = {
- "Midi", "Drum", "Wave", "AudioOut", "AudioIn", "AudioGroup",
- "AudioAux", "AudioSynth"
+ "Midi", "Drum", "NewStyleDrum", "Wave",
+ "AudioOut", "AudioIn", "AudioGroup", "AudioAux", "AudioSynth"
};
@@ -331,6 +334,7 @@ void Track::setDefaultName(QString base)
switch(_type) {
case MIDI:
case DRUM:
+ case NEW_DRUM:
case WAVE:
base = QString("Track");
break;
@@ -522,6 +526,11 @@ MidiTrack::MidiTrack()
_events = new EventList;
_mpevents = new MPEventList;
clefType=trebleClef;
+
+ _drummap=new DrumMap[128];
+ _drummap_hidden=new bool[128];
+
+ init_drummap(true /* write drummap ordering information as well */);
}
MidiTrack::MidiTrack(const MidiTrack& mt, int flags)
@@ -529,6 +538,12 @@ MidiTrack::MidiTrack(const MidiTrack& mt, int flags)
{
_events = new EventList;
_mpevents = new MPEventList;
+
+ _drummap=new DrumMap[128];
+ _drummap_hidden=new bool[128];
+
+ init_drummap(true /* write drummap ordering information as well */);
+
internal_assign(mt, flags | Track::ASSIGN_PROPERTIES);
}
@@ -564,6 +579,14 @@ void MidiTrack::internal_assign(const Track& t, int flags)
for(ciRoute ir = mt._outRoutes.begin(); ir != mt._outRoutes.end(); ++ir)
// Amazingly, this single line seems to work.
MusEGlobal::audio->msgAddRoute(Route(this, ir->channel), *ir);
+
+ for (MusEGlobal::global_drum_ordering_t::iterator it=MusEGlobal::global_drum_ordering.begin(); it!=MusEGlobal::global_drum_ordering.end(); it++)
+ if (it->first == &mt)
+ {
+ it=MusEGlobal::global_drum_ordering.insert(it, *it); // duplicates the entry at it, set it to the first entry of both
+ it++; // make it point to the second entry
+ it->first=this;
+ }
}
else if(flags & ASSIGN_DEFAULT_ROUTES)
{
@@ -614,6 +637,16 @@ void MidiTrack::internal_assign(const Track& t, int flags)
}
}
+ if (flags & ASSIGN_DRUMLIST)
+ {
+ for (int i=0;i<128;i++) // no memcpy allowed here. dunno exactly why,
+ _drummap[i]=mt._drummap[i]; // seems QString-related.
+ memcpy(_drummap_hidden, mt._drummap_hidden, 128*sizeof(bool));
+ update_drum_in_map();
+ _drummap_tied_to_patch=mt._drummap_tied_to_patch;
+ _drummap_ordering_tied_to_patch=mt._drummap_ordering_tied_to_patch;
+ // TODO FINDMICH "assign" ordering as well
+ }
}
void MidiTrack::assign(const Track& t, int flags)
@@ -626,8 +659,21 @@ MidiTrack::~MidiTrack()
{
delete _events;
delete _mpevents;
+ delete [] _drummap;
+ delete [] _drummap_hidden;
+
+ remove_ourselves_from_drum_ordering();
}
+void MidiTrack::remove_ourselves_from_drum_ordering()
+{
+ for (MusEGlobal::global_drum_ordering_t::iterator it=MusEGlobal::global_drum_ordering.begin(); it!=MusEGlobal::global_drum_ordering.end();)
+ if (it->first == this)
+ it=MusEGlobal::global_drum_ordering.erase(it);
+ else
+ it++;
+}
+
//---------------------------------------------------------
// init
//---------------------------------------------------------
@@ -635,7 +681,7 @@ MidiTrack::~MidiTrack()
void MidiTrack::init()
{
_outPort = 0;
- _outChannel = 0;
+ _outChannel = (type()==NEW_DRUM) ? 9 : 0;
//_inPortMask = 0xffff;
///_inPortMask = 0xffffffff;
@@ -648,6 +694,44 @@ void MidiTrack::init()
_recEcho = true;
}
+void MidiTrack::init_drum_ordering()
+{
+ // first display entries with non-empty names, then with empty names.
+
+ remove_ourselves_from_drum_ordering();
+
+ for (int i=0;i<128;i++)
+ if (_drummap[i].name!="" && _drummap[i].name!="?") // non-empty name?
+ MusEGlobal::global_drum_ordering.push_back(std::pair<MidiTrack*,int>(this,i));
+
+ for (int i=0;i<128;i++)
+ if (!(_drummap[i].name!="" && _drummap[i].name!="?")) // empty name?
+ MusEGlobal::global_drum_ordering.push_back(std::pair<MidiTrack*,int>(this,i));
+}
+
+void MidiTrack::init_drummap(bool write_ordering)
+{
+ for (int i=0;i<128;i++)
+ _drummap[i]=iNewDrumMap[i];
+
+ if (write_ordering)
+ init_drum_ordering();
+
+ update_drum_in_map();
+
+ for (int i=0;i<128;i++)
+ _drummap_hidden[i]=false;
+
+ _drummap_tied_to_patch=true;
+ _drummap_ordering_tied_to_patch=true;
+}
+
+void MidiTrack::update_drum_in_map()
+{
+ for (int i=0;i<127;i++)
+ drum_in_map[(int)_drummap[i].enote]=i;
+}
+
//---------------------------------------------------------
// height
//---------------------------------------------------------
@@ -905,8 +989,13 @@ void MidiTrack::write(int level, Xml& xml) const
if (type() == DRUM)
tag = "drumtrack";
- else
+ else if (type() == MIDI)
tag = "miditrack";
+ else if (type() == NEW_DRUM)
+ tag = "newdrumtrack";
+ else
+ printf("THIS SHOULD NEVER HAPPEN: non-midi-type in MidiTrack::write()\n");
+
xml.tag(level++, tag);
Track::writeProperties(level, xml);
@@ -929,9 +1018,29 @@ void MidiTrack::write(int level, Xml& xml) const
const PartList* pl = cparts();
for (ciPart p = pl->begin(); p != pl->end(); ++p)
p->second->write(level, xml);
+
+ writeOurDrumSettings(level, xml);
+
xml.etag(level, tag);
}
+void MidiTrack::writeOurDrumSettings(int level, Xml& xml) const
+{
+ xml.tag(level++, "our_drum_settings");
+
+ writeOurDrumMap(level, xml, false);
+
+ xml.intTag(level, "tied", _drummap_tied_to_patch);
+ xml.intTag(level, "ordering_tied", _drummap_ordering_tied_to_patch);
+
+ xml.etag(level, "our_drum_settings");
+}
+
+void MidiTrack::writeOurDrumMap(int level, Xml& xml, bool full) const
+{
+ write_new_style_drummap(level, xml, "our_drummap", _drummap, _drummap_hidden, full);
+}
+
//---------------------------------------------------------
// MidiTrack::read
//---------------------------------------------------------
@@ -988,6 +1097,8 @@ void MidiTrack::read(Xml& xml)
setAutomationType(AutomationType(xml.parseInt()));
else if (tag == "clef")
clefType = (clefTypes)xml.parseInt();
+ else if (tag == "our_drum_settings")
+ readOurDrumSettings(xml);
else if (Track::readProperties(xml, tag)) {
// version 1.0 compatibility:
if (tag == "track" && xml.majorVersion() == 1 && xml.minorVersion() == 0)
@@ -998,7 +1109,7 @@ void MidiTrack::read(Xml& xml)
case Xml::Attribut:
break;
case Xml::TagEnd:
- if (tag == "miditrack" || tag == "drumtrack")
+ if (tag == "miditrack" || tag == "drumtrack" || tag == "newdrumtrack")
{
setInPortAndChannelMask(portmask, chanmask); // Support old files.
return;
@@ -1009,6 +1120,46 @@ void MidiTrack::read(Xml& xml)
}
}
+void MidiTrack::readOurDrumSettings(Xml& xml)
+{
+ for (;;)
+ {
+ Xml::Token token = xml.parse();
+ if (token == Xml::Error || token == Xml::End)
+ break;
+ const QString& tag = xml.s1();
+ switch (token)
+ {
+ case Xml::TagStart:
+ if (tag == "tied")
+ _drummap_tied_to_patch = xml.parseInt();
+ else if (tag == "ordering_tied")
+ _drummap_ordering_tied_to_patch = xml.parseInt();
+ else if (tag == "our_drummap")
+ readOurDrumMap(xml);
+ else
+ xml.unknown("MidiTrack::readOurDrumSettings");
+ break;
+
+ case Xml::TagEnd:
+ if (tag == "our_drum_settings")
+ return;
+
+ default:
+ break;
+ }
+ }
+}
+
+void MidiTrack::readOurDrumMap(Xml& xml, bool dont_init)
+{
+ if (!dont_init) init_drummap(false);
+ _drummap_tied_to_patch=false;
+ _drummap_ordering_tied_to_patch=false;
+ read_new_style_drummap(xml, "our_drummap", _drummap, _drummap_hidden);
+ update_drum_in_map();
+}
+
//---------------------------------------------------------
// addPart
@@ -1195,4 +1346,69 @@ void Track::writeRouting(int level, Xml& xml) const
}
}
+int MidiTrack::getFirstControllerValue(int ctrl, int def)
+{
+ int val=def;
+ unsigned tick=-1; // maximum integer
+
+ for (iPart pit=parts()->begin(); pit!=parts()->end(); pit++)
+ {
+ Part* part=pit->second;
+ if (part->tick() > tick) break; // ignore this and the rest. we won't find anything new.
+ for (iEvent eit=part->events()->begin(); eit!=part->events()->end(); eit++)
+ {
+ if (eit->first+part->tick() >= tick) break;
+ // else if (eit->first+part->tick() < tick) and
+ if (eit->second.type()==Controller && eit->second.dataA()==ctrl)
+ {
+ val = eit->second.dataB();
+ tick = eit->first+part->tick();
+ break;
+ }
+ }
+ }
+
+ return val;
+}
+
+
+// returns true if the autoupdate changed something
+bool MidiTrack::auto_update_drummap()
+{
+ if (_drummap_tied_to_patch)
+ {
+ int patch = getFirstControllerValue(CTRL_PROGRAM,0);
+ const DrumMap* new_drummap = MusEGlobal::midiPorts[_outPort].instrument()->drummap_for_patch(patch);
+
+ if (!drummaps_almost_equal(new_drummap, this->drummap(), 128))
+ {
+ for (int i=0;i<128;i++)
+ {
+ bool temp_mute=_drummap[i].mute;
+ _drummap[i]=new_drummap[i];
+ _drummap[i].mute=temp_mute;
+ }
+
+ if (_drummap_ordering_tied_to_patch)
+ init_drum_ordering();
+
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void MidiTrack::set_drummap_tied_to_patch(bool val)
+{
+ _drummap_tied_to_patch=val;
+ if (val) auto_update_drummap();
+}
+
+void MidiTrack::set_drummap_ordering_tied_to_patch(bool val)
+{
+ _drummap_ordering_tied_to_patch=val;
+ if (val && _drummap_tied_to_patch) init_drum_ordering();
+}
+
} // namespace MusECore