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; }  | 
