1 //=========================================================
2 //  MusE
3 //  Linux Music Editor
4 //  $Id: midictrl.h,v 1.16.2.8 2009/11/25 09:09:43 terminator356 Exp $
5 //
6 //  (C) Copyright 1999-2003 Werner Schweer (ws@seh.de)
7 //  (C) Copyright 2012 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 __MIDICTRL_H__
26 #define __MIDICTRL_H__
27 
28 #include <map>
29 
30 #include "midi_controller.h"
31 
32 //#define _MIDI_CTRL_DEBUG_
33 // For finding exactly who may be calling insert, erase clear etc. in
34 //  the controller list classes. (KDevelop 'Find uses'.)
35 //#define _MIDI_CTRL_METHODS_DEBUG_
36 
37 namespace MusECore {
38 
39 class Part;
40 class MidiRecordEvent;
41 
42 struct MidiCtrlVal
43 {
44   // The part containing the event which this value came from. Used for searching and deleting.
45   Part* part;
46   // The stored value.
47   int val;
MidiCtrlValMidiCtrlVal48   MidiCtrlVal(Part* p, int v) { part = p; val = v; }
49   bool operator==(const MidiCtrlVal& mcv) { return part == mcv.part && val == mcv.val; }
50 };
51 
52 //---------------------------------------------------------
53 //   MidiCtrlValList
54 //    arrange controller events of a specific type in a
55 //    list for easy retrieval
56 //---------------------------------------------------------
57 
58 typedef std::pair<unsigned int, MidiCtrlVal> MidiCtrlValListInsertPair_t;
59 typedef std::multimap<unsigned int, MidiCtrlVal, std::less<unsigned int> > MidiCtrlValList_t;
60 
61 class MidiCtrlValList : public MidiCtrlValList_t {
62 
63       // The controller number.
64       int ctrlNum;
65       // Current set value in midi hardware. Can be CTRL_VAL_UNKNOWN.
66       double _hwVal;
67       // The last value that was not CTRL_VAL_UNKNOWN. Can still be CTRL_VAL_UNKNOWN (typically at startup).
68       // Note that in the case of PROGRAM for example, HBank/LBank bytes can still be 0xff (OFF).
69       double _lastValidHWVal;
70       // The last byte values that were not CTRL_VAL_UNKNOWN or 0xff (Off).
71       // Can never be 0xff (OFF), but can still be CTRL_VAL_UNKNOWN (typically at startup).
72       // Special for example PROGRAM controller, has 3 separate values: HBank, LBank and Program.
73       int _lastValidByte2;
74       int _lastValidByte1;
75       int _lastValidByte0;
76 
77       // Hide built-in finds.
find(const unsigned int &)78       iterator find(const unsigned int&) { return end(); };
find(const unsigned int &)79       const_iterator find(const unsigned int&) const { return end(); };
80 
81    public:
82       MidiCtrlValList(int num);
83 
84       Part* partAtTick(unsigned int tick) const;
85 
86       // Determine value at tick, using values stored by ANY part.
87       iterator iValue(unsigned int tick);
88       // Determine value at tick, using values stored by ANY part.
89       int value(unsigned int tick) const;
90       // Determine value at tick, using values stored by the SPECIFIC part.
91       int value(unsigned int tick, Part* part) const;
92       // Determine value at tick, using values stored by ANY part,
93       //  ignoring values that are OUTSIDE of their parts, or muted or off parts or tracks.
94       int visibleValue(unsigned int tick, bool inclMutedParts, bool inclMutedTracks, bool inclOffTracks) const;
95       // Determine value at tick, using values stored by the SPECIFIC part,
96       //  ignoring values that are OUTSIDE of the part, or muted or off part or track.
97       int visibleValue(unsigned int tick, Part* part, bool inclMutedParts, bool inclMutedTracks, bool inclOffTracks) const;
98       // Adds the new value. Accepts duplicate controller items at the same position, to accurately reflect
99       //  what is really in the event lists.
100 // REMOVE Tim. Ctrl. Changed comment.
101 //       // Mostly for the purpose of dragging and dropping controller events and allowing them to be
102 //       //  on top of each other TEMPORARILY.
103 //       // But ultimately once dropping is finished there must be only ONE value per controller
104 //       //  per position per part.
105       // NOTE: It is FORBIDDEN to have multiple controller events at the same time with the same controller number.
106       // To preserve speed, we RELY on catching that at higher levels like the add event dialog or during song loading.
107       // See detailed comments in EventList::add().
108       bool addMCtlVal(unsigned int tick, int value, Part* part);
109       // If val is not -1 it will search for that value.
110       void delMCtlVal(unsigned int tick, Part* part, int val/* = -1*/);
111 
112       // If val is not -1 it will search for that value.
113       iterator findMCtlVal(unsigned int tick, Part* part, int val/* = -1*/);
114 
115       // Current set value in midi hardware. Can be CTRL_VAL_UNKNOWN.
hwVal()116       inline int hwVal() const { return MidiController::dValToInt(_hwVal); }
117 
hwDVal()118       double hwDVal() const { return _hwVal; }
hwValIsUnknown()119       inline bool hwValIsUnknown() const { return MidiController::iValIsUnknown(MidiController::dValToInt(_hwVal)); }
120 
121       // Resets the current, and optionally the last, hardware value to CTRL_VAL_UNKNOWN.
122       // Returns true if either value was changed.
123       bool resetHwVal(bool doLastHwValue = false);
124 
125       // Set current value in midi hardware. Can be CTRL_VAL_UNKNOWN.
126       // Returns false if value is already equal, true if value is changed.
127       bool setHwVal(const double v);
128       //   Sets current and last HW values.
129       //   Handy for forcing labels to show 'off' and knobs to show specific values
130       //    without having to send two messages.
131       //   Returns false if both values are already set, true if either value is changed.
132       bool setHwVals(const double v, const double lastv);
133       // The controller number.
num()134       int num() const { return ctrlNum; }
135       // The last value that was not CTRL_VAL_UNKNOWN. Can still be CTRL_VAL_UNKNOWN (typically at startup).
136       // Note that in the case of PROGRAM for example, HBank/LBank bytes can still be 0xff (OFF).
lastValidHWVal()137       inline int lastValidHWVal() const { return MidiController::dValToInt(_lastValidHWVal); }
138 
lastValidHWDVal()139       double lastValidHWDVal() const { return _lastValidHWVal; }
lastHwValIsUnknown()140       inline bool lastHwValIsUnknown() const { return MidiController::iValIsUnknown(MidiController::dValToInt(_lastValidHWVal)); }
141 
142       // The last byte values that were not CTRL_VAL_UNKNOWN or 0xff (Off).
143       // Can never be 0xff (OFF), but can still be CTRL_VAL_UNKNOWN (typically at startup).
144       // Special for example PROGRAM controller, has 3 separate values: HBank, LBank and Program.
lastValidByte2()145       int lastValidByte2() const          { return _lastValidByte2; }
lastValidByte1()146       int lastValidByte1() const          { return _lastValidByte1; }
lastValidByte0()147       int lastValidByte0() const          { return _lastValidByte0; }
148       };
149 
150 typedef MidiCtrlValList::iterator iMidiCtrlVal;
151 typedef MidiCtrlValList::const_iterator ciMidiCtrlVal;
152 typedef std::pair <iMidiCtrlVal, iMidiCtrlVal> MidiCtrlValRange;
153 
154 //---------------------------------------------------------
155 //   MidiCtrlValListList
156 //    List of midi controller value lists.
157 //    This list represents the controller state of a
158 //    midi port.
159 //          index = (channelNumber << 24) + ctrlNumber
160 //---------------------------------------------------------
161 
162 typedef std::map<int, MidiCtrlValList*, std::less<int> > MidiCtrlValListList_t;
163 typedef MidiCtrlValListList_t::iterator iMidiCtrlValList;
164 typedef MidiCtrlValListList_t::const_iterator ciMidiCtrlValList;
165 
166 class MidiCtrlValListList : public MidiCtrlValListList_t {
167       bool _RPN_Ctrls_Reserved;
168 
169    public:
170       MidiCtrlValListList();
171       //MidiCtrlValListList(const MidiCtrlValListList&); // TODO
172 
find(int channel,int ctrl)173       iterator find(int channel, int ctrl) {
174             return std::map<int, MidiCtrlValList*, std::less<int> >::find((channel << 24) + ctrl);
175             }
find(int channel,int ctrl)176       const_iterator find(int channel, int ctrl) const {
177             return ((const MidiCtrlValListList_t*)this)->find((channel << 24) + ctrl);
178             }
179       void clearDelete(bool deleteLists);
180       // Like 'find', finds a controller given fully qualified type + number.
181       // But it returns controller with highest priority if multiple controllers use the
182       //  given number such as {Controller7, num = 0x55} + {Controller14, num = 0x5544}.
183       // Note if given number is one of the eight reserved General Midi (N)RPN controllers,
184       //  this will only return Controller7 or Controller14, not anything (N)RPN related.
185       // That is, it will not 'encode' (N)RPNs. Use a MidiEncoder instance for that.
186       iMidiCtrlValList searchControllers(int channel, int ctl);
187       // Returns true if any of the EIGHT reserved General Midi (N)RPN control numbers are ALREADY
188       //  defined as Controller7 or part of Controller14. Cached, for speed.
189       // Used (at least) by midi input encoders to quickly arbitrate new input.
RPN_Ctrls_Reserved()190       bool RPN_Ctrls_Reserved() { return _RPN_Ctrls_Reserved; }
191       // Manual check and update of the flag. For convenience, returns the flag.
192       // Cost depends on types and number of list controllers, so it is good for deferring
193       //  an update until AFTER some lengthy list operation. JUST BE SURE to call this!
194       bool update_RPN_Ctrls_Reserved();
195 
196       // NOTICE: If update is false or these are bypassed by using insert, erase, clear etc. for speed,
197       //          then BE SURE to call update_RPN_Ctrls_Reserved() later.
198       void add(int channel, MidiCtrlValList* vl, bool update = true);
199       void del(iMidiCtrlValList ictl, bool update = true);
200       size_type del(int num, bool update = true);
201       void del(iMidiCtrlValList first, iMidiCtrlValList last, bool update = true);
202       void clr();
203       // Convenience method: Resets all current, and optionally the last, hardware controller values to CTRL_VAL_UNKNOWN.
204       // Equivalent to calling resetAllHwVal() on each MidiCtrlValList.
205       // Returns true if either value was changed in any controller.
206       bool resetAllHwVals(bool doLastHwValue);
207 
208 #ifdef _MIDI_CTRL_METHODS_DEBUG_
209       // Need to catch all insert, erase, clear etc...
210       void swap(MidiCtrlValListList&);
211       std::pair<iMidiCtrlValList, bool> insert(const std::pair<int, MidiCtrlValList*>& p);
212       iMidiCtrlValList insert(iMidiCtrlValList ic, const std::pair<int, MidiCtrlValList*>& p);
213       void erase(iMidiCtrlValList ictl);
214       size_type erase(int num);
215       void erase(iMidiCtrlValList first, iMidiCtrlValList last);
216       void clear();
217 #endif
218       // Some IDEs won't "Find uses" of operators. So, no choice but to trust always catching it here.
219       MidiCtrlValListList& operator=(const MidiCtrlValListList&);
220       };
221 
222 //---------------------------------------------------------
223 //   MidiEncoder
224 //---------------------------------------------------------
225 
226 class MidiEncoder {
227   public:
228     enum Mode { EncIdle, EncCtrl14, EncDiscoverRPN, EncDiscoverNRPN, EncRPN, EncNRPN, EncRPN14, EncNRPN14 };
229     enum ParamMode { ParamModeUnknown, ParamModeRPN, ParamModeNRPN };
230 
231   private:
232     Mode          _curMode;
233     ParamMode     _curParamMode;
234     unsigned int  _timer;        //
235     unsigned char _curCtrl;      // Ctl num of first event
236     unsigned char _curData;      // Data of first event
237     unsigned int  _curTime;      // Time of first event
238     unsigned char _nextCtrl;     // Expected next event ctl num (for ctrl14 only)
239     unsigned char _curRPNH;
240     unsigned char _curRPNL;
241     unsigned char _curNRPNH;
242     unsigned char _curNRPNL;
243 
244   public:
245     MidiEncoder();
246 
247     void encodeEvent(const MidiRecordEvent& ev, int port, int channel);
248     void endCycle(unsigned int blockSize);
249 };
250 
251 extern MidiControllerList defaultMidiController;
252 extern void initMidiController();
253 
254 extern MidiController veloCtrl;
255 extern MidiController pitchCtrl;
256 extern MidiController programCtrl;
257 extern MidiController mastervolCtrl;
258 extern MidiController volumeCtrl;
259 extern MidiController panCtrl;
260 extern MidiController reverbSendCtrl;
261 extern MidiController chorusSendCtrl;
262 extern MidiController variationSendCtrl;
263 
264 
265 } // namespace MusECore
266 
267 #endif
268 
269