summaryrefslogtreecommitdiff
path: root/muse2/muse/instruments
diff options
context:
space:
mode:
authorFlorian Jung <flo@windfisch.org>2011-12-30 17:55:58 +0000
committerFlorian Jung <flo@windfisch.org>2011-12-30 17:55:58 +0000
commit6f35a1b2b84ab6cfc5d77fd46d5e31887a1590e1 (patch)
treeadece0e0c4fbe63659741539296df9fd32bfcaab /muse2/muse/instruments
parent4d8477ab60093fc4c1f6190a931d0c2fdc65384c (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.cpp188
-rw-r--r--muse2/muse/instruments/minstrument.h47
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; }