1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  $Id: minstrument.h,v 1.3.2.3 2009/03/09 02:05:18 terminator356 Exp $
5 //
6 //  (C) Copyright 2000 Werner Schweer (ws@seh.de)
7 //  (C) Copyright 2016 Tim E. Real (terminator356 on users dot sourceforge dot net)
8 //
9 //  This program is free software; you can redistribute it and/or
10 //  modify it under the terms of the GNU General Public License
11 //  as published by the Free Software Foundation; version 2 of
12 //  the License, or (at your option) any later version.
13 //
14 //  This program is distributed in the hope that it will be useful,
15 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 //  GNU General Public License for more details.
18 //
19 //  You should have received a copy of the GNU General Public License
20 //  along with this program; if not, write to the Free Software
21 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
22 //
23 //=========================================================
24 
25 #ifndef __MINSTRUMENT_H__
26 #define __MINSTRUMENT_H__
27 
28 #include "globaldefs.h"
29 #include <map>
30 #include <list>
31 #include <vector>
32 #include <string>
33 #include <QString>
34 #include <QList>
35 
36 #include "midiedit/drummap.h"
37 
38 #include "config.h"
39 #ifdef MIDNAM_SUPPORT
40 #include "midnam.h"
41 #endif
42 
43 #include "midictrl_consts.h"
44 
45 // REMOVE Tim. newdrums. Added.
46 // Adds the ability to override at instrument level.
47 // But it just makes things too complex for the user.
48 // And in a way is unnecessary and overkill, since we
49 //  already allow modifying an instrument.
50 //#define _USE_INSTRUMENT_OVERRIDES_
51 
52 
53 // Forward declarations:
54 namespace MusEGui {
55 class PopupMenu;
56 }
57 
58 namespace MusECore {
59 class EventList;
60 class MidiControllerList;
61 class MidiPlayEvent;
62 class Xml;
63 
64 //---------------------------------------------------------
65 //   Patch
66 //---------------------------------------------------------
67 
68 struct Patch {
69       signed char hbank, lbank, program;
70       QString name;
71       bool drum;
72 
patchPatch73       inline int patch() const { return (((unsigned int)hbank & 0xff) << 16) | (((unsigned int)lbank & 0xff) << 8) | ((unsigned int)program & 0xff); }
dontCarePatch74       inline bool dontCare()        const { return hbankDontCare() && lbankDontCare() && programDontCare(); }
hbankDontCarePatch75       inline bool hbankDontCare()   const { return hbank < 0; }
lbankDontCarePatch76       inline bool lbankDontCare()   const { return lbank < 0; }
programDontCarePatch77       inline bool programDontCare() const { return program < 0; }
78 
79       void read(Xml&);
80       void write(int level, Xml&);
81       };
82 
83 class PatchList : public std::list<Patch*> {
84   public:
85     iterator find(int patch, bool drum, bool includeDefault);
86     const_iterator find(int patch, bool drum, bool includeDefault) const;
87 };
88 
89 typedef PatchList::iterator iPatch;
90 typedef PatchList::const_iterator ciPatch;
91 
92 //---------------------------------------------------------
93 //   PatchGroup
94 //---------------------------------------------------------
95 
96 struct PatchGroup {
97       QString name;
98       PatchList patches;
99       void read(Xml&);
100       };
101 
102 class PatchGroupList : public std::vector<PatchGroup*> {
103   public:
104     Patch* findPatch(int patch, bool drum, bool includeDefault);
105     Patch* findPatch(int patch, bool drum, bool includeDefault) const;
106 };
107 
108 typedef PatchGroupList::iterator iPatchGroup;
109 typedef PatchGroupList::const_iterator ciPatchGroup;
110 
111 struct SysEx {
112       QString name;
113       QString comment;
114       int dataLen;
115       unsigned char* data;
116       bool read(Xml&);
117       void write(int level, Xml&);
118 
119       SysEx();
120       SysEx(const SysEx& src);
121       ~SysEx();
122       };
123 
124 struct dumb_patchlist_entry_t
125 {
126   int prog;
127   int lbank;
128   int hbank; // "-1" means "unused"
129 
dumb_patchlist_entry_tdumb_patchlist_entry_t130   dumb_patchlist_entry_t(int p, int l, int h)
131   {
132     prog=p;
133     lbank=l;
134     hbank=h;
135   }
136 
137   bool operator<(const dumb_patchlist_entry_t& other) const
138   {
139     if (hbank < other.hbank) return true;
140     if (hbank > other.hbank) return false;
141     if (lbank < other.lbank) return true;
142     if (lbank > other.lbank) return false;
143     return (prog < other.prog);
144   }
145 
146   bool operator>(const dumb_patchlist_entry_t& other) const
147   {
148     return other < *this;
149   }
150 
151   bool operator==(const dumb_patchlist_entry_t& other) const
152   {
153     return (prog==other.prog && lbank==other.lbank && hbank==other.hbank);
154   }
155 
156   bool operator!=(const dumb_patchlist_entry_t& other) const
157   {
158     return (!(*this==other));
159   }
160 };
161 
162 struct WorkingDrumMapEntry {
163 #ifdef _USE_INSTRUMENT_OVERRIDES_
164   enum OverrideType { NoOverride = 0x0, TrackDefaultOverride = 0x1, TrackOverride = 0x2, InstrumentDefaultOverride = 0x4, InstrumentOverride = 0x8,
165                       AllOverrides = InstrumentDefaultOverride | InstrumentOverride | TrackDefaultOverride | TrackOverride };
166 #else
167   enum OverrideType { NoOverride = 0x0, TrackDefaultOverride = 0x1, TrackOverride = 0x2,
168                       AllOverrides = TrackDefaultOverride | TrackOverride };
169 #endif
170 
171   enum Field { NoField = 0x0, NameField = 0x1, VolField = 0x2, QuantField = 0x4, LenField = 0x8, ChanField = 0x10, PortField = 0x20,
172                Lv1Field = 0x40, Lv2Field = 0x80, Lv3Field = 0x100, Lv4Field = 0x200, ENoteField = 0x400, ANoteField = 0x800,
173                MuteField = 0x1000, HideField = 0x2000,
174                AllFields = NameField | VolField | QuantField | LenField | ChanField | PortField | Lv1Field | Lv2Field | Lv3Field | Lv4Field |
175                            ENoteField | ANoteField | MuteField | HideField};
176   // OR'd Fields.
177   typedef int override_t;
178   typedef int fields_t;
179 
180   DrumMap _mapItem;
181   fields_t _fields;
182 
183   // Starts with null _mapItem.
184   WorkingDrumMapEntry();
185   // Allocates _mapItem and copies dm to it.
186   WorkingDrumMapEntry(const DrumMap& dm, fields_t fields);
187   // Copy ctor.
188   WorkingDrumMapEntry(const WorkingDrumMapEntry&);
189   WorkingDrumMapEntry& operator=(const WorkingDrumMapEntry&);
190 };
191 
192 typedef std::map < int /*index*/, WorkingDrumMapEntry, std::less<int> > WorkingDrumMapList_t;
193 typedef WorkingDrumMapList_t::iterator iWorkingDrumMapPatch_t;
194 typedef WorkingDrumMapList_t::const_iterator ciWorkingDrumMapPatch_t;
195 typedef std::pair<iWorkingDrumMapPatch_t, bool> WorkingDrumMapPatchInsertResult_t;
196 typedef std::pair<int, WorkingDrumMapEntry> WorkingDrumMapPatchInsertPair_t;
197 typedef std::pair<iWorkingDrumMapPatch_t, iWorkingDrumMapPatch_t> WorkingDrumMapPatchRangePair_t;
198 
199 class WorkingDrumMapList : public WorkingDrumMapList_t {
200 
201   public:
202     void add(int index,const WorkingDrumMapEntry& item);
203     // Returns the requested fields that were NOT removed.
204     int remove(int index, const WorkingDrumMapEntry& item);
205     // Returns the requested fields that were NOT removed.
206     int remove(int index, int fields);
207     // If fillUnused is true it will fill any unused fields.
208     void read(Xml&, bool fillUnused, int defaultIndex = -1);
209     void write(int level, Xml&) const;
210 };
211 
212 
213 typedef std::map < int /*patch*/, WorkingDrumMapList, std::less<int> > WorkingDrumMapPatchList_t;
214 typedef WorkingDrumMapPatchList_t::iterator iWorkingDrumMapPatchList_t;
215 typedef WorkingDrumMapPatchList_t::const_iterator ciWorkingDrumMapPatchList_t;
216 typedef std::pair<iWorkingDrumMapPatchList_t, bool> WorkingDrumMapPatchListInsertResult_t;
217 typedef std::pair<int, WorkingDrumMapList> WorkingDrumMapPatchListInsertPair_t;
218 
219 class WorkingDrumMapPatchList : public WorkingDrumMapPatchList_t {
220 
221   public:
222     void add(const WorkingDrumMapPatchList& other);
223     void add(int patch, const WorkingDrumMapList& list);
224     void add(int patch, int index, const WorkingDrumMapEntry& item);
225     void remove(int patch, int index, const WorkingDrumMapEntry& item, bool includeDefault);
226     void remove(int patch, int index, int fields, bool includeDefault);
227     void remove(int patch, bool includeDefault);
228     WorkingDrumMapList* find(int patch, bool includeDefault);
229     const WorkingDrumMapList* find(int patch, bool includeDefault) const;
230     WorkingDrumMapEntry* find(int patch, int index, bool includeDefault);
231     const WorkingDrumMapEntry* find(int patch, int index, bool includeDefault) const;
232 
233     // If fillUnused is true it will fill any unused items to ensure that all 128 items are filled.
234     void read(Xml&, bool fillUnused);
235     void write(int level, Xml&) const;
236 };
237 
238 
239 typedef std::map < std::string /*instrument name*/, WorkingDrumMapPatchList > WorkingDrumMapInstrumentList_t;
240 typedef WorkingDrumMapInstrumentList_t::iterator iWorkingDrumMapInstrumentList_t;
241 typedef WorkingDrumMapInstrumentList_t::const_iterator ciWorkingDrumMapInstrumentList_t;
242 typedef std::pair<iWorkingDrumMapInstrumentList_t, bool> WorkingDrumMapInstrumentListInsertResult_t;
243 typedef std::pair<std::string, WorkingDrumMapPatchList> WorkingDrumMapInstrumentListInsertPair_t;
244 
245 
246 class WorkingDrumMapInstrumentList : public WorkingDrumMapInstrumentList_t {
247   public:
248     void read(Xml&);
249 };
250 
251 struct patch_drummap_mapping_t
252 {
253   int _patch;
254   DrumMap* drummap;
255   int drum_in_map[128];
256 
257 #ifdef _USE_INSTRUMENT_OVERRIDES_
258   // A list of user-altered drum map items.
259   WorkingDrumMapList _workingDrumMapList;
260 #endif
261 
262   // A NULL drummap is allowed, it means invalid (ie. invalid() returns true).
263   patch_drummap_mapping_t(DrumMap* d, int patch = 0xffffff)
264   {
265     drummap = d;
266     _patch = patch;
267     update_drum_in_map();
268   }
269 
270   patch_drummap_mapping_t(const patch_drummap_mapping_t& that);
271   patch_drummap_mapping_t();
272   ~patch_drummap_mapping_t();
273 
274   patch_drummap_mapping_t& operator=(const patch_drummap_mapping_t& that);
275 
276 #ifdef _USE_INSTRUMENT_OVERRIDES_
277   void addWorkingDrumMapEntry(int index,const WorkingDrumMapEntry& item);
278   void removeWorkingDrumMapEntry(int index, const WorkingDrumMapEntry& item);
279   void removeWorkingDrumMapEntry(int index, int fields);
280 #endif
281 
map_drum_inpatch_drummap_mapping_t282   int map_drum_in(int enote) { return drum_in_map[enote]; }
283   void update_drum_in_map();
284 
hbankpatch_drummap_mapping_t285   inline int hbank() const { return (_patch >> 16) & 0xff; }
lbankpatch_drummap_mapping_t286   inline int lbank() const { return (_patch >> 8)  & 0xff; }
progpatch_drummap_mapping_t287   inline int prog()  const { return  _patch & 0xff; }
setHBankpatch_drummap_mapping_t288   inline void setHBank(int v) { _patch = (_patch & 0x00ffff) | ((v & 0xff) << 16); }
setLBankpatch_drummap_mapping_t289   inline void setLBank(int v) { _patch = (_patch & 0xff00ff) | ((v & 0xff) << 8); }
setProgpatch_drummap_mapping_t290   inline void setProg(int v)  { _patch = (_patch & 0xffff00) | (v & 0xff); }
dontCarepatch_drummap_mapping_t291   inline bool dontCare()        const { return hbankDontCare() && lbankDontCare() && programDontCare(); }
hbankDontCarepatch_drummap_mapping_t292   inline bool hbankDontCare()   const { const int hb = hbank(); return hb < 0 || hb > 127; }
lbankDontCarepatch_drummap_mapping_t293   inline bool lbankDontCare()   const { const int lb = lbank(); return lb < 0 || lb > 127; }
programDontCarepatch_drummap_mapping_t294   inline bool programDontCare() const { const int pr = prog();  return pr < 0 || pr > 127; }
295 
296   bool isPatchInRange(int patch, bool includeDefault) const;
297 
298   bool isValid() const;
299 
300   QString to_string();
301 };
302 
303 class patch_drummap_mapping_list_t : public std::list<patch_drummap_mapping_t>
304 {
305   public:
306     void add(const patch_drummap_mapping_list_t& other);
307     void add(const patch_drummap_mapping_t& pdm);
308     iterator find(int patch, bool includeDefault);
309     const_iterator find(int patch, bool includeDefault) const;
310     void read(Xml& xml);
311     void write(int level, Xml&) const;
312 #ifdef _USE_INSTRUMENT_OVERRIDES_
313     void writeDrummapOverrides(int level, Xml& xml) const;
314 #endif
315 };
316 
317 typedef patch_drummap_mapping_list_t::iterator iPatchDrummapMapping_t;
318 typedef patch_drummap_mapping_list_t::const_iterator ciPatchDrummapMapping_t;
319 
320 
321 // NOTE: Channel == -1 (default) is legal.
322 typedef std::map < int /*channel*/, patch_drummap_mapping_list_t, std::less<int> > ChannelDrumMappingList_t;
323 typedef ChannelDrumMappingList_t::iterator iChannelDrumMappingList_t;
324 typedef ChannelDrumMappingList_t::const_iterator ciChannelDrumMappingList_t;
325 typedef std::pair<iChannelDrumMappingList_t, bool> ChannelDrumMappingListInsertResult_t;
326 typedef std::pair<int, patch_drummap_mapping_list_t> ChannelDrumMappingListInsertPair_t;
327 
328 class ChannelDrumMappingList : public ChannelDrumMappingList_t {
329   public:
330     ChannelDrumMappingList();
331 
332     void add(const ChannelDrumMappingList& other);
333     void add(int channel, const patch_drummap_mapping_list_t& list);
334     //void add(int patch, int index, const WorkingDrumMapEntry& item);
335     //void remove(int patch, int index, const WorkingDrumMapEntry& item, bool includeDefault);
336     //void remove(int patch, int index, int fields, bool includeDefault);
337     //void remove(int patch, bool includeDefault);
338     patch_drummap_mapping_list_t* find(int channel, bool includeDefault);
339     const patch_drummap_mapping_list_t* find(int channel, bool includeDefault) const;
340     //WorkingDrumMapEntry* find(int patch, int index, bool includeDefault);
341     //const WorkingDrumMapEntry* find(int patch, int index, bool includeDefault) const;
342 
343     // If fillUnused is true it will fill any unused items to ensure that all 128 items are filled.
344     void read(Xml&);
345     void write(int level, Xml&) const;
346 };
347 
348 
349 //---------------------------------------------------------
350 //   MidiInstrument
351 //---------------------------------------------------------
352 
353 class MidiInstrument {
354    public:
355      //              NoteOffAll  = Use all note offs.
356      //              NoteOffNone = Do not use any note offs.
357      // NoteOffConvertToZVNoteOn = Convert all note offs to zero-velocity note ons.
358      enum NoteOffMode { NoteOffAll=0, NoteOffNone, NoteOffConvertToZVNoteOn };
359 
360    private:
361       PatchGroupList pg;
362       MidiControllerList* _controller;
363       QList<SysEx*> _sysex;
364       ChannelDrumMappingList _channelDrumMapping;
365       bool _dirty;
366       bool _waitForLSB; // Whether 14-bit controllers wait for LSB, or MSB and LSB are separate.
367       NoteOffMode _noteOffMode;
368 
369       void init();
370 
371    protected:
372       EventList* _midiInit;
373       EventList* _midiReset;
374       EventList* _midiState;
375       // Set when loading midi state in SynthI::read, to indicate version
376       //  to SynthI::initInstance, which is called later.
377       int        _tmpMidiStateVersion;
378       char* _initScript;
379       QString _name;
380       QString _filePath;
381 
382 #ifdef MIDNAM_SUPPORT
383       MidNamMIDIName _midnamDocument;
384 #endif
385 
386       void writeDrummaps(int level, Xml& xml) const;
387       void readDrummaps(Xml& xml);
388 
389    public:
390       MidiInstrument();
391       virtual ~MidiInstrument();
392       MidiInstrument(const QString& txt);
iname()393       const QString& iname() const      { return _name; }
setIName(const QString & txt)394       void setIName(const QString& txt) { _name = txt; }
395       MType midiType() const;
isSynti()396       virtual bool isSynti() const     { return false; }
397 
398       // Assign will 'delete' all existing patches and groups from the instrument.
399       MidiInstrument& assign(const MidiInstrument&);
filePath()400       QString filePath() const               { return _filePath;   }
setFilePath(const QString & s)401       void setFilePath(const QString& s)     { _filePath = s;      }
dirty()402       bool dirty() const                     { return _dirty;      }
setDirty(bool v)403       void setDirty(bool v)                  { _dirty = v;         }
404 
sysex()405       const QList<SysEx*>& sysex() const     { return _sysex; }
removeSysex(SysEx * sysex)406       void removeSysex(SysEx* sysex)         { _sysex.removeAll(sysex); }
addSysex(SysEx * sysex)407       void addSysex(SysEx* sysex)            { _sysex.append(sysex); }
408 
409 
410       QList<dumb_patchlist_entry_t> getPatches(int channel, bool drum);
411       unsigned getNextPatch(int channel, unsigned patch, bool drum);
412       unsigned getPrevPatch(int channel, unsigned patch, bool drum);
413 #ifdef _USE_INSTRUMENT_OVERRIDES_
414       bool setWorkingDrumMapItem(int patch, int index, const WorkingDrumMapEntry&, bool isReset);
415       // Returns OR'd WorkingDrumMapEntry::OverrideType flags indicating whether a map item's members,
416       //  given by 'fields' (OR'd WorkingDrumMapEntry::Fields), are either the original or working map item.
417       // Here in MidiInstrument the flags can be NoOverride and InstrumentOverride. See corresponding function
418       //  in MidiTrack for additional TrackOverride flag use.
419       int isWorkingMapItem(int patch, int index, int fields) const;
420       void clearDrumMapOverrides();
421 #endif
422       // Returns a map item with members filled from either the original or working map item,
423       //  depending on which Field flags are set. The returned map includes any requested
424       //  WorkingDrumMapEntry::OverrideType instrument overrides. Channel can be -1 meaning default.
425       virtual void getMapItem(int channel, int patch, int index, DrumMap& dest_map,
426                               int overrideType = WorkingDrumMapEntry::AllOverrides) const;
427 
midiInit()428       EventList* midiInit() const            { return _midiInit; }
midiReset()429       EventList* midiReset() const           { return _midiReset; }
midiState()430       EventList* midiState() const           { return _midiState; }
initScript()431       const char* initScript() const         { return _initScript; }
controller()432       MidiControllerList* controller() const { return _controller; }
waitForLSB()433       bool waitForLSB() { return _waitForLSB; }
setWaitForLSB(bool v)434       void setWaitForLSB(bool v) { _waitForLSB = v; }
435 
436       // Finds a controller. By default it looks in this instrument's MidiControllerList map
437       //  just like calling the map's find(). But if channel or patch are given (not default),
438       //  it looks in BOTH the midnam's MidiControllerList and the instrument's MidiControllerList.
439       // In other words, the instrument's list acts as a default for all channels and patches,
440       //  and has no 'channel' or 'patch number'. The midnam's list takes priority if used.
441       // Like find() which finds a verbose ctl number, but this version also finds a per-note
442       //  controller if there is one for the given ctl number, if no verbose one was found. The ctl
443       //  number can be the 'real' controller number, ie the low byte can be the actual note number
444       //  and does not have to be 0xff.
445       // Returns null if no such specific controller OR suitable default is found.
446       MidiController* findController(int num, int channel = -1, int patch = CTRL_PROGRAM_VAL_DONT_CARE) const;
447       // Fills a given MidiControllerList with all available controllers for a given channel and patch.
448       // By default it gathers from this instrument's MidiControllerList map just like calling controller().
449       // But if channel or patch are given (not default), it gathers from BOTH the midnam's MidiControllerList
450       //  and the instrument's MidiControllerList.
451       // This would not be suitable for realtime code since it may allocate. And it copies all the items to dest.
452       void getControllers(MidiControllerList* dest, int channel = -1, int patch = CTRL_PROGRAM_VAL_DONT_CARE) const;
453 
454       // Virtual so that inheriters (synths etc) can return whatever they want.
noteOffMode()455       virtual NoteOffMode noteOffMode() const { return _noteOffMode; }
456       // For non-synths, users can set this value.
setNoteOffMode(NoteOffMode mode)457       void setNoteOffMode(NoteOffMode mode) { _noteOffMode = mode; }
458 
459       void readMidiState(Xml& xml);
460       virtual void reset(int);
461       virtual QString getPatchName(int channel, int prog, bool drum, bool includeDefault) const;
462       virtual void populatePatchPopup(MusEGui::PopupMenu*, int, bool);
463       static void populateInstrPopup(MusEGui::PopupMenu*, int port, bool show_synths = false);  // Static
464       void read(Xml&);
465       void write(int level, Xml&);
466 #ifdef _USE_INSTRUMENT_OVERRIDES_
467       void writeDrummapOverrides(int level, Xml&) const;
468 #endif
469 
470 #ifdef MIDNAM_SUPPORT
midnamDocument()471       MidNamMIDIName& midnamDocument() { return _midnamDocument; }
midnamDocument()472       const MidNamMIDIName& midnamDocument() const { return _midnamDocument; }
473       // Possible plan: Use this INSTEAD of a direct call to MidNamMIDIName::read()
474       //  so that we can catch it and update some stuff here afterwards (controllers).
475       bool readMidnamDocument(Xml&);
476 #endif
477 
groups()478       PatchGroupList* groups()        { return &pg; }
479       patch_drummap_mapping_list_t* get_patch_drummap_mapping(int channel, bool includeDefault);
getChannelDrumMapping()480       ChannelDrumMappingList* getChannelDrumMapping() { return &_channelDrumMapping; }
481       };
482 
483 //---------------------------------------------------------
484 //   MidiInstrumentList
485 //---------------------------------------------------------
486 
487 class MidiInstrumentList : public std::list<MidiInstrument*> {
488 
489    public:
MidiInstrumentList()490       MidiInstrumentList() {}
491       iterator find(const MidiInstrument* instr);
492 #ifdef _USE_INSTRUMENT_OVERRIDES_
493       void writeDrummapOverrides(int level, Xml&) const;
494 #endif
495       };
496 
497 typedef MidiInstrumentList::iterator iMidiInstrument;
498 typedef MidiInstrumentList::const_iterator ciMidiInstrument;
499 
500 extern MidiInstrumentList midiInstruments;
501 extern MidiInstrument* genericMidiInstrument;
502 extern void initMidiInstruments();
503 extern MidiInstrument* registerMidiInstrument(const QString&);
504 extern void removeMidiInstrument(const QString& name);
505 extern void removeMidiInstrument(const MidiInstrument* instr);
506 
507 } // namespace MusECore
508 
509 #ifdef _USE_INSTRUMENT_OVERRIDES_
510 namespace MusEGlobal {
511   extern MusECore::WorkingDrumMapInstrumentList workingDrumMapInstrumentList;
512 }
513 #endif
514 
515 #endif
516 
517