diff options
author | Florian Jung <flo@windfisch.org> | 2011-12-30 17:55:58 +0000 |
---|---|---|
committer | Florian Jung <flo@windfisch.org> | 2011-12-30 17:55:58 +0000 |
commit | 6f35a1b2b84ab6cfc5d77fd46d5e31887a1590e1 (patch) | |
tree | adece0e0c4fbe63659741539296df9fd32bfcaab /muse2/muse/instruments | |
parent | 4d8477ab60093fc4c1f6190a931d0c2fdc65384c (diff) |
instruments can load their patch'es drummaps
automatic setting of drummap according to patch
this is turned off when the user manually changes the drummap
TODO: let him turn it on again
moved MidiTrack::read/writeOurDrummap out to helper.cpp
extended xg.idf and gs.idf to ship the drummaps
still work in progress, but should be usable and stable, though incomplete
Diffstat (limited to 'muse2/muse/instruments')
-rw-r--r-- | muse2/muse/instruments/minstrument.cpp | 188 | ||||
-rw-r--r-- | muse2/muse/instruments/minstrument.h | 47 |
2 files changed, 233 insertions, 2 deletions
diff --git a/muse2/muse/instruments/minstrument.cpp b/muse2/muse/instruments/minstrument.cpp index a01903ae..3876fb28 100644 --- a/muse2/muse/instruments/minstrument.cpp +++ b/muse2/muse/instruments/minstrument.cpp @@ -41,6 +41,8 @@ #include "midictrl.h" #include "gconfig.h" #include "popupmenu.h" +#include "drummap.h" +#include "helper.h" namespace MusECore { @@ -364,6 +366,7 @@ void MidiInstrument::init() MidiController* prog = new MidiController("Program", CTRL_PROGRAM, 0, 0xffffff, 0); _controller->add(prog); _dirty = false; + } MidiInstrument::MidiInstrument() @@ -408,8 +411,20 @@ MidiInstrument::~MidiInstrument() if (_initScript) delete _initScript; + + clear_delete_patch_drummap_mapping(); } +void MidiInstrument::clear_delete_patch_drummap_mapping() +{ + for (std::list<patch_drummap_mapping_t>::iterator it = patch_drummap_mapping.begin(); + it!=patch_drummap_mapping.end(); it++) + delete[] it->drummap; + + patch_drummap_mapping.clear(); +} + + /* //--------------------------------------------------------- // uniqueCopy @@ -515,7 +530,20 @@ MidiInstrument& MidiInstrument::assign(const MidiInstrument& ins) _name = ins._name; _filePath = ins._filePath; - + + clear_delete_patch_drummap_mapping(); + // do a deep copy + for (std::list<patch_drummap_mapping_t>::const_iterator it = ins.patch_drummap_mapping.begin(); + it!=ins.patch_drummap_mapping.end(); it++) + { + patch_drummap_mapping_t temp = *it; + temp.drummap=new DrumMap[128]; + for (int i=0;i<128;i++) + temp.drummap[i]=it->drummap[i]; + } + + + // Hmm, dirty, yes? But init sets it to false... //_dirty = ins._dirty; //_dirty = false; @@ -733,6 +761,123 @@ void MidiInstrument::readMidiState(Xml& xml) } } +void MidiInstrument::readDrummaps(Xml& xml) +{ + clear_delete_patch_drummap_mapping(); + + for (;;) + { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) + { + case Xml::Error: + case Xml::End: + return; + + case Xml::TagStart: + if (tag == "entry") + patch_drummap_mapping.push_back(readDrummapsEntry(xml)); + else + xml.unknown("MidiInstrument::readDrummaps"); + break; + + case Xml::TagEnd: + if (tag == "Drummaps") + return; + + default: + break; + } + } + printf("ERROR: THIS CANNOT HAPPEN: exited infinite loop in MidiInstrument::readDrummaps()!\n" + " not returning anything. expect undefined behaviour or even crashes.\n"); +} + +patch_drummap_mapping_t MidiInstrument::readDrummapsEntry(Xml& xml) +{ + using std::list; + + list<patch_collection_t> collection; + DrumMap* drummap=new DrumMap[128]; + for (int i=0;i<128;i++) + drummap[i]=iNewDrumMap[i]; + + for (;;) + { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) + { + case Xml::Error: + case Xml::End: + return patch_drummap_mapping_t(collection, drummap); + + case Xml::TagStart: + if (tag == "patch_collection") + collection.push_back(readDrummapsEntryPatchCollection(xml)); + else if (tag == "drummap") + read_new_style_drummap(xml, "drummap", drummap); + else + xml.unknown("MidiInstrument::readDrummapsEntry"); + break; + + case Xml::TagEnd: + if (tag == "entry") + return patch_drummap_mapping_t(collection, drummap); + + default: + break; + } + } + printf("ERROR: THIS CANNOT HAPPEN: exited infinite loop in MidiInstrument::readDrummapsEntry()!\n" + " not returning anything. expect undefined behaviour or even crashes.\n"); + return patch_drummap_mapping_t(); +} + +patch_collection_t MidiInstrument::readDrummapsEntryPatchCollection(Xml& xml) +{ + int first_prog=0, last_prog=256; // this means: + int first_lbank=0, last_lbank=256; // "does not matter" + int first_hbank=0, last_hbank=256; + + for (;;) + { + Xml::Token token = xml.parse(); + const QString& tag = xml.s1(); + switch (token) + { + case Xml::Error: + case Xml::End: + return patch_collection_t(-1,-1,-1,-1,-1,-1); // an invalid collection + + case Xml::TagStart: + xml.unknown("MidiInstrument::readDrummapsEntryPatchCollection"); + break; + + case Xml::Attribut: + if (tag == "prog") + parse_range(xml.s2(), &first_prog, &last_prog); + else if (tag == "lbank") + parse_range(xml.s2(), &first_lbank, &last_lbank); + else if (tag == "hbank") + parse_range(xml.s2(), &first_hbank, &last_hbank); + break; + + case Xml::TagEnd: + if (tag == "patch_collection") + return patch_collection_t(first_prog, last_prog, first_lbank, last_lbank, first_hbank, last_hbank); + + default: + break; + } + } + + printf("ERROR: THIS CANNOT HAPPEN: exited infinite loop in MidiInstrument::readDrummapsEntryPatchCollection()!\n" + " not returning anything. expect undefined behaviour or even crashes.\n"); +} + + //--------------------------------------------------------- // read //--------------------------------------------------------- @@ -785,6 +930,9 @@ void MidiInstrument::read(Xml& xml) _controller->add(mc); } + else if (tag == "Drummaps") { + readDrummaps(xml); + } else if (tag == "Init") readEventList(xml, _midiInit, "Init"); else if (tag == "Reset") @@ -794,7 +942,7 @@ void MidiInstrument::read(Xml& xml) else if (tag == "InitScript") { if (_initScript) delete _initScript; - QByteArray ba = xml.parse1().toLatin1(); + QByteArray ba = xml.parse1().toLatin1(); const char* istr = ba.constData(); int len = strlen(istr) +1; if (len > 1) { @@ -998,4 +1146,40 @@ void MidiInstrument::populatePatchPopup(MusEGui::PopupMenu* menu, int chan, MTyp } +const DrumMap* MidiInstrument::drummap_for_patch(int patch) const +{ + using std::list; + + int program = (patch & 0x0000FF); + int lbank = (patch & 0x00FF00) >> 8; + int hbank = (patch & 0xFF0000) >> 16; + + for (list<patch_drummap_mapping_t>::const_iterator it=patch_drummap_mapping.begin(); + it!=patch_drummap_mapping.end(); it++) + { + for (list<patch_collection_t>::const_iterator it2=it->affected_patches.begin(); + it2!=it->affected_patches.end(); it2++) + { + // if the entry matches our patch + if ( (program >= it2->first_program && program <= it2->last_program) && + (hbank >= it2->first_hbank && hbank <= it2->last_hbank) && + (lbank >= it2->first_lbank && lbank <= it2->last_lbank) ) + { + return it->drummap; + } + } + } + + // if nothing was found + return iNewDrumMap; +} + +patch_drummap_mapping_t::patch_drummap_mapping_t() +{ + drummap=new DrumMap[128]; + for (int i=0;i<128;i++) + drummap[i]=iNewDrumMap[i]; +} + + } // namespace MusECore diff --git a/muse2/muse/instruments/minstrument.h b/muse2/muse/instruments/minstrument.h index 385e67b4..9a65598b 100644 --- a/muse2/muse/instruments/minstrument.h +++ b/muse2/muse/instruments/minstrument.h @@ -40,6 +40,7 @@ class MidiControllerList; class MidiPort; class MidiPlayEvent; class Xml; +class DrumMap; //--------------------------------------------------------- @@ -80,6 +81,43 @@ struct SysEx { unsigned char* data; }; + + +struct patch_collection_t +{ + int first_program; + int last_program; + int first_hbank; + int last_hbank; + int first_lbank; + int last_lbank; + + patch_collection_t(int p1=0, int p2=127, int l1=0, int l2=127, int h1=0, int h2=127) + { + first_program=p1; + last_program=p2; + first_lbank=l1; + last_lbank=l2; + first_hbank=h1; + last_hbank=h2; + } + +}; + +struct patch_drummap_mapping_t +{ + std::list<patch_collection_t> affected_patches; + DrumMap* drummap; + + patch_drummap_mapping_t(const std::list<patch_collection_t>& a, DrumMap* d) + { + affected_patches=a; + drummap=d; + } + + patch_drummap_mapping_t(); +}; + //--------------------------------------------------------- // MidiInstrument //--------------------------------------------------------- @@ -88,6 +126,7 @@ class MidiInstrument { PatchGroupList pg; MidiControllerList* _controller; QList<SysEx*> _sysex; + std::list<patch_drummap_mapping_t> patch_drummap_mapping; bool _dirty; int _nullvalue; @@ -103,6 +142,12 @@ class MidiInstrument { char* _initScript; QString _name; QString _filePath; + + void clear_delete_patch_drummap_mapping(); + + void readDrummaps(Xml& xml); + patch_drummap_mapping_t readDrummapsEntry(Xml& xml); + patch_collection_t readDrummapsEntryPatchCollection(Xml& xml); public: MidiInstrument(); @@ -123,6 +168,8 @@ class MidiInstrument { void removeSysex(SysEx* sysex) { _sysex.removeAll(sysex); } void addSysex(SysEx* sysex) { _sysex.append(sysex); } + const DrumMap* drummap_for_patch(int patch) const; + EventList* midiInit() const { return _midiInit; } EventList* midiReset() const { return _midiReset; } EventList* midiState() const { return _midiState; } |