summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2011-10-09 13:20:51 +0000
committerFlorian Jung <flo@windfisch.org>2011-10-09 13:20:51 +0000
commit159a2b58fd28c7a00b9b723dcea77e6c2ec2e874 (patch)
treeac8427059e7786cf63e33949201394e88a6222da
parent9cd7615aaa5bc2818ae5f9425173f08673bbc194 (diff)
updated MidiTrack::read and ::write
-rw-r--r--muse2/muse/midiedit/drummap.cpp9
-rw-r--r--muse2/muse/midiedit/drummap.h1
-rw-r--r--muse2/muse/midiedit/scoreedit.cpp6
-rw-r--r--muse2/muse/track.cpp245
-rw-r--r--muse2/muse/track.h9
5 files changed, 246 insertions, 24 deletions
diff --git a/muse2/muse/midiedit/drummap.cpp b/muse2/muse/midiedit/drummap.cpp
index 43e66345..47232011 100644
--- a/muse2/muse/midiedit/drummap.cpp
+++ b/muse2/muse/midiedit/drummap.cpp
@@ -43,6 +43,15 @@ namespace MusECore {
const DrumMap blankdm = { QString(""), 100, 16, 32, 9, 0, 70, 90, 127, 110, 127, 127, false };
+// this map must have 128 entries, as it's used for initalising new-style-drummaps as well.
+// new-style-drummaps only have 128 entries. also, the every "out-note" ("anote") must be
+// represented exactly once in that map, and there may be no duplicate or unused "out-notes".
+// reason: the track's drummap are inited as follows: iterate through the full idrumMap[],
+// tracks_drummap[ idrumMap[i].anote ] = idrumMap[i]
+// if you ever want to change this, you will need to go through track.cpp/.h and
+// {dlist,dcanvas,drumedit,drummap}{.cpp,.h} (and possibly some more) and find every usage
+// of idrumMap by new style drummaps, and fix the problem. a possible fix would be duplicating
+// idrumMap, change idrumMap, and use the duplicate for the new style stuff instead.
const DrumMap idrumMap[DRUM_MAPSIZE] = {
{ QString("Acoustic Bass Drum"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 35, 35, false },
{ QString("Bass Drum 1"), 100, 16, 32, 9, 0, 70, 90, 127, 110, 36, 36, false },
diff --git a/muse2/muse/midiedit/drummap.h b/muse2/muse/midiedit/drummap.h
index f3186afa..3b6ffaf3 100644
--- a/muse2/muse/midiedit/drummap.h
+++ b/muse2/muse/midiedit/drummap.h
@@ -51,6 +51,7 @@ struct DrumMap {
bool operator!=(const DrumMap& map) const { return !operator==(map); }
};
+// please let this at "128". idrumMap must have length 128 (see drummap.cpp for details)
#define DRUM_MAPSIZE 128
extern const DrumMap idrumMap[DRUM_MAPSIZE]; //FINDMICH dummy!
diff --git a/muse2/muse/midiedit/scoreedit.cpp b/muse2/muse/midiedit/scoreedit.cpp
index 5770ee6c..8f647966 100644
--- a/muse2/muse/midiedit/scoreedit.cpp
+++ b/muse2/muse/midiedit/scoreedit.cpp
@@ -4608,7 +4608,7 @@ void ScoreCanvas::add_new_parts(const std::map< MusECore::Part*, std::set<MusECo
* o clearly state in the changelog: when having multiple drumeditors open,
* the mute-column may not work, because another editor is overriding this.
* o respect "_drummap_tied_to_patch": IMPLEMENT
- * o save hide, ordering, track's drumlists
+ * o allow loading and saving track-drumlists to external files
* o "copy drumlist" from one track to another
* o whenever changing the patch and maintained_automatically==true,
* the drumlist is replaced by the according one (for example, "jazz" drum kit's list)
@@ -4616,11 +4616,13 @@ void ScoreCanvas::add_new_parts(const std::map< MusECore::Part*, std::set<MusECo
* ask the user if he wants to proceed, and then set maintained_automatically to false
* o offer some way to set maintained_automatically to true again
* o move generation and deletion of ourDrumMap from DCanvas to DrumEditor and remove ugly wrapper functions
+ * x save hide, ordering, track's drumlists
*
* x when playing back a flo-drum-track: treat as a MIDI track,
* EXCEPT that the drum list's mute entries are respected!
* o when recording or echoing a flo-drum-track: watch out for In-Notes!
- * o update [midi]track::read/write, readproperties, writeprop... (drumlist etc), operator=
+ * * update [midi]track::read/write, readproperties, writeprop... (drumlist etc), operator=
+ * _should_ be okay, but i'm not sure
*
* IMPORTANT TODO
* o all places where i added doubleclick-edits: only react on left-click double clicks!
diff --git a/muse2/muse/track.cpp b/muse2/muse/track.cpp
index 32344b6e..e24ddad9 100644
--- a/muse2/muse/track.cpp
+++ b/muse2/muse/track.cpp
@@ -405,19 +405,7 @@ MidiTrack::MidiTrack()
_drummap=new DrumMap[128];
_drummap_hidden=new bool[128];
- for (int i=0;i<128;i++)
- {
- int idx=idrumMap[i].anote;
- if (idx < 0 || idx >= 128)
- printf ("ERROR: THIS SHOULD NEVER HAPPEN: idrumMap[%i].anote is not within 0..127!\n", idx);
- else
- _drummap[idx]=idrumMap[i];
-
- MusEGlobal::global_drum_ordering.push_back(std::pair<MidiTrack*,int>(this,idx));
- }
- for (int i=0;i<128;i++)
- _drummap_hidden[i]=false;
-
+ init_drummap(true /* write drummap ordering information as well */);
}
//MidiTrack::MidiTrack(const MidiTrack& mt)
@@ -460,16 +448,18 @@ MidiTrack::~MidiTrack()
delete [] _drummap;
delete [] _drummap_hidden;
- // remove ourselves from the global_drum_ordering list
- // this is not really necessary, but cleaner
- 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++;
-
+ 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
//---------------------------------------------------------
@@ -491,6 +481,26 @@ void MidiTrack::init()
_recEcho = true;
}
+void MidiTrack::init_drummap(bool write_ordering)
+{
+ for (int i=0;i<128;i++)
+ {
+ int idx=idrumMap[i].anote;
+ if (idx < 0 || idx >= 128)
+ printf ("ERROR: THIS SHOULD NEVER HAPPEN: idrumMap[%i].anote is not within 0..127!\n", idx);
+ else
+ _drummap[idx]=idrumMap[i];
+
+ if (write_ordering)
+ MusEGlobal::global_drum_ordering.push_back(std::pair<MidiTrack*,int>(this,idx));
+ }
+
+ for (int i=0;i<128;i++)
+ _drummap_hidden[i]=false;
+}
+
+
+
//---------------------------------------------------------
// height
//---------------------------------------------------------
@@ -793,9 +803,77 @@ 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");
+
+ xml.intTag(level, "tied", _drummap_tied_to_patch);
+
+ writeOurDrumMap(level, xml);
+
+ xml.etag(level, "our_drum_settings");
+}
+
+void MidiTrack::writeOurDrumMap(int level, Xml& xml) const
+{
+ xml.tag(level++, "our_drummap");
+
+ for (int i=0;i<128;i++)
+ {
+ int j;
+ for (j=0;j<128;j++)
+ if (idrumMap[j].anote == i) break;
+
+ if (j==128)
+ printf("THIS SHOULD NEVER HAPPEN: couldn't find initial drum map entry in MidiTrack::writeOurDrumMap()\n");
+ else
+ {
+ DrumMap* dm = &_drummap[i];
+ const DrumMap* idm = &idrumMap[j];
+
+ if ( (dm->name != idm->name) || (dm->vol != idm->vol) ||
+ (dm->quant != idm->quant) || (dm->len != idm->len) ||
+ (dm->lv1 != idm->lv1) || (dm->lv2 != idm->lv2) ||
+ (dm->lv3 != idm->lv3) || (dm->lv4 != idm->lv4) ||
+ (dm->enote != idm->enote) || (dm->mute != idm->mute) ||
+ _drummap_hidden[i] )
+ {
+ xml.tag(level++, "entry pitch=\"%d\"", i);
+
+ // when any of these "if"s changes, also update the large "if"
+ // above (this scope's parent)
+ if (dm->name != idm->name) xml.strTag(level, "name", dm->name);
+ if (dm->vol != idm->vol) xml.intTag(level, "vol", dm->vol);
+ if (dm->quant != idm->quant) xml.intTag(level, "quant", dm->quant);
+ if (dm->len != idm->len) xml.intTag(level, "len", dm->len);
+ if (dm->lv1 != idm->lv1) xml.intTag(level, "lv1", dm->lv1);
+ if (dm->lv2 != idm->lv2) xml.intTag(level, "lv2", dm->lv2);
+ if (dm->lv3 != idm->lv3) xml.intTag(level, "lv3", dm->lv3);
+ if (dm->lv4 != idm->lv4) xml.intTag(level, "lv4", dm->lv4);
+ if (dm->enote != idm->enote) xml.intTag(level, "enote", dm->enote);
+ if (dm->mute != idm->mute) xml.intTag(level, "mute", dm->mute);
+ if (_drummap_hidden[i]) xml.intTag(level, "hide", _drummap_hidden[i]);
+
+ // anote is ignored anyway, as dm->anote == i, and this is
+ // already stored in the begin tag (pitch=...)
+
+ // channel and port are ignored as well, as they're not used
+ // in new-style-drum-mode
+
+ xml.tag(level--, "/entry");
+ }
+ }
+ }
+
+ xml.etag(level, "our_drummap");
+}
+
//---------------------------------------------------------
// MidiTrack::read
//---------------------------------------------------------
@@ -852,6 +930,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)
@@ -873,6 +953,129 @@ 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 == "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)
+{
+ init_drummap(false);
+
+ 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 == "entry") // then read that entry with a nested loop
+ {
+ DrumMap* dm=NULL;
+ bool* hidden=NULL;
+ for (;;) // nested loop
+ {
+ Xml::Token token = xml.parse();
+ const QString& tag = xml.s1();
+ switch (token)
+ {
+ case Xml::Error:
+ case Xml::End:
+ goto end_of_nested_for;
+
+ case Xml::Attribut:
+ if (tag == "pitch")
+ {
+ int pitch = xml.s2().toInt() & 0x7f;
+ if (pitch < 0 || pitch > 127)
+ printf("ERROR: THIS SHOULD NEVER HAPPEN: invalid pitch in MidiTrack::readOurDrumMap()!\n");
+ else
+ {
+ dm = &_drummap[pitch];
+ hidden = &_drummap_hidden[pitch];
+ }
+ }
+ break;
+
+ case Xml::TagStart:
+ if (dm==NULL)
+ printf("ERROR: THIS SHOULD NEVER HAPPEN: no valid 'pitch' attribute in <entry> tag, but sub-tags follow in MidiTrack::readOurDrumMap()!\n");
+ else if (tag == "name")
+ dm->name = xml.parse(QString("name"));
+ else if (tag == "vol")
+ dm->vol = (unsigned char)xml.parseInt();
+ else if (tag == "quant")
+ dm->quant = xml.parseInt();
+ else if (tag == "len")
+ dm->len = xml.parseInt();
+ else if (tag == "lv1")
+ dm->lv1 = xml.parseInt();
+ else if (tag == "lv2")
+ dm->lv2 = xml.parseInt();
+ else if (tag == "lv3")
+ dm->lv3 = xml.parseInt();
+ else if (tag == "lv4")
+ dm->lv4 = xml.parseInt();
+ else if (tag == "enote")
+ dm->enote = xml.parseInt();
+ else if (tag == "mute")
+ dm->mute = xml.parseInt();
+ else if (tag == "hide")
+ *hidden = xml.parseInt();
+ else
+ xml.unknown("MidiTrack::readOurDrumMap");
+ break;
+
+ case Xml::TagEnd:
+ if (tag == "entry")
+ goto end_of_nested_for;
+
+ default:
+ break;
+ }
+ } // end of nested loop
+ end_of_nested_for: ;
+ } // end of 'if (tag == "entry")'
+ else
+ xml.unknown("MidiTrack::readOurDrumMap");
+ break;
+
+ case Xml::TagEnd:
+ if (tag == "our_drummap")
+ return;
+
+ default:
+ break;
+ }
+ }
+}
+
//---------------------------------------------------------
// addPart
diff --git a/muse2/muse/track.h b/muse2/muse/track.h
index 0911b4f1..a958ca74 100644
--- a/muse2/muse/track.h
+++ b/muse2/muse/track.h
@@ -230,10 +230,17 @@ class MidiTrack : public Track {
clefTypes clefType;
DrumMap* _drummap; // _drummap[foo].anote is always equal to foo
+ bool* _drummap_hidden; // _drummap und _drummap_hidden will be an array[128]
bool _drummap_tied_to_patch; //if true, changing patch also changes drummap
- bool* _drummap_hidden;
void init();
+ void init_drummap(bool write_ordering=false);
+ void remove_ourselves_from_drum_ordering();
+
+ void writeOurDrumSettings(int level, Xml& xml) const;
+ void writeOurDrumMap(int level, Xml& xml) const;
+ void readOurDrumSettings(Xml& xml);
+ void readOurDrumMap(Xml& xml);
public:
MidiTrack();