andrewm@0
|
1 /*
|
andrewm@0
|
2 TouchKeys: multi-touch musical keyboard control software
|
andrewm@0
|
3 Copyright (c) 2013 Andrew McPherson
|
andrewm@0
|
4
|
andrewm@0
|
5 This program is free software: you can redistribute it and/or modify
|
andrewm@0
|
6 it under the terms of the GNU General Public License as published by
|
andrewm@0
|
7 the Free Software Foundation, either version 3 of the License, or
|
andrewm@0
|
8 (at your option) any later version.
|
andrewm@0
|
9
|
andrewm@0
|
10 This program is distributed in the hope that it will be useful,
|
andrewm@0
|
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
|
andrewm@0
|
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
andrewm@0
|
13 GNU General Public License for more details.
|
andrewm@0
|
14
|
andrewm@0
|
15 You should have received a copy of the GNU General Public License
|
andrewm@0
|
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
|
andrewm@0
|
17
|
andrewm@0
|
18 =====================================================================
|
andrewm@0
|
19
|
andrewm@0
|
20 TouchkeyBaseMappingFactory.h: base factory class specifically for
|
andrewm@0
|
21 TouchKeys mappings. It provides a collection of useful methods for
|
andrewm@0
|
22 creating and destroying individual mappings on touch/MIDI onset and
|
andrewm@0
|
23 release, as well as parameter adjustment code and OSC to MIDI conversion.
|
andrewm@0
|
24 This is a template class that must be created with a specific Mapping
|
andrewm@0
|
25 subclass.
|
andrewm@0
|
26 */
|
andrewm@0
|
27
|
andrewm@0
|
28 #ifndef __TouchKeys__TouchkeyBaseMappingFactory__
|
andrewm@0
|
29 #define __TouchKeys__TouchkeyBaseMappingFactory__
|
andrewm@0
|
30
|
andrewm@0
|
31 #include <iostream>
|
andrewm@0
|
32 #include <map>
|
andrewm@0
|
33 #include <sstream>
|
andrewm@0
|
34 #include "MappingFactory.h"
|
andrewm@0
|
35 #include "../TouchKeys/OscMidiConverter.h"
|
andrewm@0
|
36 #include "../TouchKeys/MidiOutputController.h"
|
andrewm@0
|
37 #include "../TouchKeys/MidiKeyboardSegment.h"
|
andrewm@0
|
38 #include "MappingScheduler.h"
|
andrewm@0
|
39
|
andrewm@0
|
40 #undef DEBUG_TOUCHKEY_BASE_MAPPING_FACTORY
|
andrewm@0
|
41
|
andrewm@0
|
42 // Base class for mapping factories that meet the following criteria:
|
andrewm@0
|
43 // * MIDI and TouchKeys data (no continuous angle)
|
andrewm@0
|
44 // * Mappings begin when either or touch or MIDI starts and end when both finish
|
andrewm@0
|
45 // * Each mapping object affects a single note
|
andrewm@0
|
46
|
andrewm@0
|
47 template <class MappingType>
|
andrewm@0
|
48 class TouchkeyBaseMappingFactory : public MappingFactory {
|
andrewm@0
|
49
|
andrewm@0
|
50 public:
|
andrewm@0
|
51 // ***** Constructor *****
|
andrewm@0
|
52
|
andrewm@0
|
53 // Default constructor, containing a reference to the PianoKeyboard class.
|
andrewm@0
|
54 TouchkeyBaseMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment) :
|
andrewm@0
|
55 MappingFactory(keyboard), keyboardSegment_(segment), midiConverter_(0),
|
andrewm@0
|
56 controlName_(""),
|
andrewm@0
|
57 inputRangeMin_(0.0), inputRangeMax_(1.0), inputRangeCenter_(0.0),
|
andrewm@0
|
58 outOfRangeBehavior_(OscMidiConverter::kOutOfRangeClip),
|
andrewm@0
|
59 midiControllerNumber_(-1), bypassed_(false), activeNotes_(0x0FFF) {}
|
andrewm@0
|
60
|
andrewm@0
|
61 // ***** Destructor *****
|
andrewm@0
|
62
|
andrewm@0
|
63 virtual ~TouchkeyBaseMappingFactory() {
|
andrewm@0
|
64 removeAllMappings();
|
andrewm@0
|
65 if(midiConverter_ != 0 && controlName_ != "")
|
andrewm@0
|
66 midiConverter_->removeControl(controlName_.c_str());
|
andrewm@0
|
67 if(midiControllerNumber_ >= 0) {
|
andrewm@0
|
68 keyboardSegment_.releaseOscMidiConverter(midiControllerNumber_);
|
andrewm@0
|
69 }
|
andrewm@0
|
70 }
|
andrewm@0
|
71
|
andrewm@0
|
72 // ***** Accessors / Modifiers *****
|
andrewm@0
|
73
|
andrewm@0
|
74 // Return the keyboard segment associated with this factory
|
andrewm@0
|
75 MidiKeyboardSegment& segment() { return keyboardSegment_; }
|
andrewm@0
|
76
|
andrewm@0
|
77 // Look up a mapping with the given note number
|
andrewm@0
|
78 virtual MappingType* mapping(int noteNumber) {
|
andrewm@0
|
79 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
80 if(mappings_.count(noteNumber) == 0)
|
andrewm@0
|
81 return 0;
|
andrewm@0
|
82 return mappings_[noteNumber];
|
andrewm@0
|
83 }
|
andrewm@0
|
84
|
andrewm@0
|
85 // Return a list of all active notes
|
andrewm@0
|
86 virtual std::vector<int> activeMappings() {
|
andrewm@0
|
87 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
88 std::vector<int> keys;
|
andrewm@0
|
89 typename std::map<int, MappingType*>::iterator it = mappings_.begin();
|
andrewm@0
|
90 while(it != mappings_.end()) {
|
andrewm@0
|
91 int nextKey = (it++)->first;
|
andrewm@0
|
92 keys.push_back(nextKey);
|
andrewm@0
|
93 }
|
andrewm@0
|
94 return keys;
|
andrewm@0
|
95 }
|
andrewm@0
|
96
|
andrewm@0
|
97 // Remove all active mappings
|
andrewm@0
|
98 virtual void removeAllMappings() {
|
andrewm@0
|
99 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
100 typename std::map<int, MappingType*>::iterator it = mappings_.begin();
|
andrewm@0
|
101
|
andrewm@0
|
102 while(it != mappings_.end()) {
|
andrewm@0
|
103 // Delete everybody in the container
|
andrewm@0
|
104 MappingType *mapping = it->second;
|
andrewm@0
|
105 #ifdef NEW_MAPPING_SCHEDULER
|
andrewm@0
|
106 mapping->disengage(true);
|
andrewm@0
|
107 //keyboard_.mappingScheduler().unscheduleAndDelete(mapping);
|
andrewm@0
|
108 #else
|
andrewm@0
|
109 mapping->disengage();
|
andrewm@0
|
110 delete mapping;
|
andrewm@0
|
111 #endif
|
andrewm@0
|
112 it++;
|
andrewm@0
|
113 }
|
andrewm@0
|
114
|
andrewm@0
|
115 // Now clear the container
|
andrewm@0
|
116 mappings_.clear();
|
andrewm@0
|
117 }
|
andrewm@0
|
118
|
andrewm@0
|
119 // Callback from mapping to say it's finished
|
andrewm@0
|
120 virtual void mappingFinished(int noteNumber) {
|
andrewm@0
|
121 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
122 removeMapping(noteNumber);
|
andrewm@0
|
123 }
|
andrewm@0
|
124
|
andrewm@0
|
125 // Suspend messages from a particular note
|
andrewm@0
|
126 virtual void suspendMapping(int noteNumber) {
|
andrewm@0
|
127 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
128 if(mappings_.count(noteNumber) == 0)
|
andrewm@0
|
129 return;
|
andrewm@0
|
130 mappings_[noteNumber]->suspend();
|
andrewm@0
|
131 }
|
andrewm@0
|
132
|
andrewm@0
|
133 // Suspend messages from all notes
|
andrewm@0
|
134 virtual void suspendAllMappings() {
|
andrewm@0
|
135 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
136 typename std::map<int, MappingType*>::iterator it = mappings_.begin();
|
andrewm@0
|
137
|
andrewm@0
|
138 while(it != mappings_.end()) {
|
andrewm@0
|
139 //std::cout << "suspending mapping on note " << it->first << std::endl;
|
andrewm@0
|
140 it->second->suspend();
|
andrewm@0
|
141 it++;
|
andrewm@0
|
142 }
|
andrewm@0
|
143 }
|
andrewm@0
|
144
|
andrewm@0
|
145 // Resume messages from a particular note
|
andrewm@0
|
146 virtual void resumeMapping(int noteNumber, bool resend) {
|
andrewm@0
|
147 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
148 if(mappings_.count(noteNumber) == 0)
|
andrewm@0
|
149 return;
|
andrewm@0
|
150 //std::cout << "resuming mapping on note " << noteNumber << std::endl;
|
andrewm@0
|
151 mappings_[noteNumber]->resume(resend);
|
andrewm@0
|
152 }
|
andrewm@0
|
153
|
andrewm@0
|
154 // Resume messages on all notes
|
andrewm@0
|
155 virtual void resumeAllMappings(bool resend) {
|
andrewm@0
|
156 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
157 typename std::map<int, MappingType*>::iterator it = mappings_.begin();
|
andrewm@0
|
158
|
andrewm@0
|
159 while(it != mappings_.end()) {
|
andrewm@0
|
160 it->second->resume(resend);
|
andrewm@0
|
161 it++;
|
andrewm@0
|
162 }
|
andrewm@0
|
163 }
|
andrewm@0
|
164
|
andrewm@0
|
165 // Whether this mapping is bypassed
|
andrewm@0
|
166 virtual int bypassed() {
|
andrewm@0
|
167 return bypassed_ ? kBypassOn : kBypassOff;
|
andrewm@0
|
168 }
|
andrewm@0
|
169
|
andrewm@0
|
170 // Set whether the mapping is bypassed or not
|
andrewm@0
|
171 virtual void setBypassed(bool bypass) {
|
andrewm@0
|
172 bypassed_ = bypass;
|
andrewm@0
|
173 }
|
andrewm@0
|
174
|
andrewm@0
|
175 // ***** Class-Specific Methods *****
|
andrewm@0
|
176
|
andrewm@0
|
177 virtual void setMidiParameters(int controller, float inputMinValue, float inputMaxValue, float inputCenterValue,
|
andrewm@0
|
178 int outputDefaultValue = -1, int outputMinValue = -1, int outputMaxValue = -1,
|
andrewm@0
|
179 int outputCenterValue = -1, bool use14BitControl = false,
|
andrewm@0
|
180 int outOfRangeBehavior = OscMidiConverter::kOutOfRangeClip) {
|
andrewm@0
|
181 if(controller < 0)
|
andrewm@0
|
182 return;
|
andrewm@0
|
183
|
andrewm@0
|
184 inputRangeMin_ = inputMinValue;
|
andrewm@0
|
185 inputRangeMax_ = inputMaxValue;
|
andrewm@0
|
186 inputRangeCenter_ = inputCenterValue;
|
andrewm@0
|
187 outOfRangeBehavior_ = outOfRangeBehavior;
|
andrewm@0
|
188
|
andrewm@0
|
189 // Remove listener on previous name (if any)
|
andrewm@0
|
190 //midiConverter_.removeAllControls();
|
andrewm@0
|
191 if(midiControllerNumber_ >= 0 && controller != midiControllerNumber_) {
|
andrewm@0
|
192 keyboardSegment_.releaseOscMidiConverter(midiControllerNumber_);
|
andrewm@0
|
193 midiConverter_ = keyboardSegment_.acquireOscMidiConverter(controller);
|
andrewm@0
|
194 }
|
andrewm@0
|
195 else if(midiControllerNumber_ < 0 || midiConverter_ == 0) {
|
andrewm@0
|
196 midiConverter_ = keyboardSegment_.acquireOscMidiConverter(controller);
|
andrewm@0
|
197 }
|
andrewm@0
|
198 midiControllerNumber_ = controller;
|
andrewm@0
|
199
|
andrewm@0
|
200 midiConverter_->setMidiMessageType(outputDefaultValue, outputMinValue, outputMaxValue, outputCenterValue, use14BitControl);
|
andrewm@0
|
201
|
andrewm@0
|
202 // Add listener for new name
|
andrewm@0
|
203 if(controlName_ != "")
|
andrewm@0
|
204 midiConverter_->addControl(controlName_.c_str(), 1, inputRangeMin_, inputRangeMax_, inputRangeCenter_, outOfRangeBehavior_);
|
andrewm@0
|
205 }
|
andrewm@0
|
206
|
andrewm@0
|
207 virtual string const getName() { return controlName_; }
|
andrewm@0
|
208
|
andrewm@0
|
209 virtual void setName(const string& name) {
|
andrewm@0
|
210 if(name == "")
|
andrewm@0
|
211 return;
|
andrewm@0
|
212 std::stringstream ss;
|
andrewm@0
|
213
|
andrewm@0
|
214 // Remove listener on previous name (if any)
|
andrewm@0
|
215 if(midiConverter_ != 0 && controlName_ != "")
|
andrewm@0
|
216 midiConverter_->removeControl(controlName_.c_str());
|
andrewm@0
|
217
|
andrewm@0
|
218 ss << "/touchkeys/mapping/segment" << (int)keyboardSegment_.outputPort() << "/" << name;
|
andrewm@0
|
219 controlName_ = ss.str();
|
andrewm@0
|
220
|
andrewm@0
|
221 // Add listener for new name
|
andrewm@0
|
222 if(midiConverter_ != 0)
|
andrewm@0
|
223 midiConverter_->addControl(controlName_.c_str(), 1, inputRangeMin_, inputRangeMax_, inputRangeCenter_, outOfRangeBehavior_);
|
andrewm@0
|
224 }
|
andrewm@0
|
225
|
andrewm@0
|
226 // Set which keys should have this mapping enable
|
andrewm@0
|
227 virtual void setActiveNotes(unsigned int notes) {
|
andrewm@0
|
228 activeNotes_ = notes;
|
andrewm@0
|
229 }
|
andrewm@0
|
230
|
andrewm@33
|
231 // ****** Preset Save/Load ******
|
andrewm@33
|
232
|
andrewm@33
|
233 // These generate XML settings files and reload settings from them
|
andrewm@33
|
234
|
andrewm@33
|
235 virtual XmlElement* getPreset() {
|
andrewm@33
|
236 XmlElement* presetElement = new XmlElement("MappingFactory");
|
andrewm@33
|
237 presetElement->setAttribute("type", "Unknown");
|
andrewm@33
|
238 return presetElement;
|
andrewm@33
|
239 }
|
andrewm@33
|
240
|
andrewm@33
|
241 virtual bool loadPreset(XmlElement const* preset) { return true; }
|
andrewm@33
|
242
|
andrewm@0
|
243 // ***** State Updaters *****
|
andrewm@0
|
244
|
andrewm@0
|
245 // These are called by PianoKey whenever certain events occur that might
|
andrewm@0
|
246 // merit the start and stop of a mapping. What is done with them depends on
|
andrewm@0
|
247 // the particular factory subclass.
|
andrewm@0
|
248
|
andrewm@0
|
249 // Touch becomes active on a key where it wasn't previously
|
andrewm@0
|
250 virtual void touchBegan(int noteNumber, bool midiNoteIsOn, bool keyMotionActive,
|
andrewm@0
|
251 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
252 Node<key_position>* positionBuffer,
|
andrewm@0
|
253 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
254 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
255 // Add a new mapping if one doesn't exist already
|
andrewm@0
|
256 if(mappings_.count(noteNumber) == 0) {
|
andrewm@0
|
257 #ifdef DEBUG_TOUCHKEY_BASE_MAPPING_FACTORY
|
andrewm@0
|
258 std::cout << "Note " << noteNumber << ": adding mapping (touch)\n";
|
andrewm@0
|
259 #endif
|
andrewm@0
|
260 int moduloNoteNumber = noteNumber % 12;
|
andrewm@0
|
261 if((activeNotes_ & (1 << moduloNoteNumber)) && !bypassed_)
|
andrewm@0
|
262 addMapping(noteNumber, touchBuffer, positionBuffer, positionTracker);
|
andrewm@0
|
263 }
|
andrewm@0
|
264 }
|
andrewm@0
|
265
|
andrewm@0
|
266 // Touch ends on a key where it wasn't previously
|
andrewm@0
|
267 virtual void touchEnded(int noteNumber, bool midiNoteIsOn, bool keyMotionActive,
|
andrewm@0
|
268 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
269 Node<key_position>* positionBuffer,
|
andrewm@0
|
270 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
271 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
272 // If a mapping exists but the MIDI note is off, remove the mapping
|
andrewm@0
|
273 if(mappings_.count(noteNumber) != 0 && !midiNoteIsOn) {
|
andrewm@0
|
274 #ifdef DEBUG_TOUCHKEY_BASE_MAPPING_FACTORY
|
andrewm@0
|
275 std::cout << "Note " << noteNumber << ": removing mapping (touch)\n";
|
andrewm@0
|
276 #endif
|
andrewm@0
|
277 if(mappings_[noteNumber]->requestFinish())
|
andrewm@0
|
278 removeMapping(noteNumber);
|
andrewm@0
|
279 }
|
andrewm@0
|
280 }
|
andrewm@0
|
281
|
andrewm@0
|
282 // MIDI note on for a key
|
andrewm@0
|
283 virtual void midiNoteOn(int noteNumber, bool touchIsOn, bool keyMotionActive,
|
andrewm@0
|
284 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
285 Node<key_position>* positionBuffer,
|
andrewm@0
|
286 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
287 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
288 // Add a new mapping if one doesn't exist already
|
andrewm@0
|
289 if(mappings_.count(noteNumber) == 0) {
|
andrewm@0
|
290 #ifdef DEBUG_TOUCHKEY_BASE_MAPPING_FACTORY
|
andrewm@0
|
291 std::cout << "Note " << noteNumber << ": adding mapping (MIDI)\n";
|
andrewm@0
|
292 #endif
|
andrewm@0
|
293 int moduloNoteNumber = noteNumber % 12;
|
andrewm@0
|
294 if((activeNotes_ & (1 << moduloNoteNumber)) && !bypassed_)
|
andrewm@0
|
295 addMapping(noteNumber, touchBuffer, positionBuffer, positionTracker);
|
andrewm@0
|
296 }
|
andrewm@0
|
297 }
|
andrewm@0
|
298
|
andrewm@0
|
299 // MIDI note off for a key
|
andrewm@0
|
300 virtual void midiNoteOff(int noteNumber, bool touchIsOn, bool keyMotionActive,
|
andrewm@0
|
301 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
302 Node<key_position>* positionBuffer,
|
andrewm@0
|
303 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
304 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
305 // If a mapping exists but the touch is off, remove the mapping
|
andrewm@0
|
306 if(mappings_.count(noteNumber) != 0 && !touchIsOn) {
|
andrewm@0
|
307 #ifdef DEBUG_TOUCHKEY_BASE_MAPPING_FACTORY
|
andrewm@0
|
308 std::cout << "Note " << noteNumber << ": removing mapping (MIDI)\n";
|
andrewm@0
|
309 #endif
|
andrewm@0
|
310 if(mappings_[noteNumber]->requestFinish())
|
andrewm@0
|
311 removeMapping(noteNumber);
|
andrewm@0
|
312 }
|
andrewm@0
|
313 }
|
andrewm@0
|
314
|
andrewm@0
|
315 // Subclasses of this one won't care about these two methods:
|
andrewm@0
|
316
|
andrewm@0
|
317 // Key goes active from continuous key position
|
andrewm@0
|
318 virtual void keyMotionActive(int noteNumber, bool midiNoteIsOn, bool touchIsOn,
|
andrewm@0
|
319 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
320 Node<key_position>* positionBuffer,
|
andrewm@0
|
321 KeyPositionTracker* positionTracker) {}
|
andrewm@0
|
322 // Key goes idle from continuous key position
|
andrewm@0
|
323 virtual void keyMotionIdle(int noteNumber, bool midiNoteIsOn, bool touchIsOn,
|
andrewm@0
|
324 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
325 Node<key_position>* positionBuffer,
|
andrewm@0
|
326 KeyPositionTracker* positionTracker) {}
|
andrewm@0
|
327
|
andrewm@0
|
328 // But we do use this one to send out default values:
|
andrewm@0
|
329 virtual void noteWillBegin(int noteNumber, int midiChannel, int midiVelocity) {
|
andrewm@0
|
330 if(midiConverter_ == 0)
|
andrewm@0
|
331 return;
|
andrewm@0
|
332 midiConverter_->clearLastValues(midiChannel, true);
|
andrewm@0
|
333 //midiConverter_->sendDefaultValue(midiChannel);
|
andrewm@0
|
334 }
|
andrewm@0
|
335
|
andrewm@0
|
336
|
andrewm@0
|
337 protected:
|
andrewm@0
|
338 // ***** Protected Methods *****
|
andrewm@0
|
339
|
andrewm@0
|
340 // This method should be set by the subclass to initialize the parameters of
|
andrewm@0
|
341 // a new mapping.
|
andrewm@0
|
342 virtual void initializeMappingParameters(int noteNumber, MappingType *mapping) {}
|
andrewm@0
|
343
|
andrewm@0
|
344 private:
|
andrewm@0
|
345 // ***** Private Methods *****
|
andrewm@0
|
346
|
andrewm@0
|
347 // Add a new mapping
|
andrewm@0
|
348 void addMapping(int noteNumber,
|
andrewm@0
|
349 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
350 Node<key_position>* positionBuffer,
|
andrewm@0
|
351 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
352 // TODO: mutex
|
andrewm@0
|
353 removeMapping(noteNumber); // Free any mapping that's already present on this note
|
andrewm@0
|
354
|
andrewm@0
|
355 MappingType *mapping = new MappingType(keyboard_, this, noteNumber, touchBuffer,
|
andrewm@0
|
356 positionBuffer, positionTracker);
|
andrewm@0
|
357
|
andrewm@0
|
358 // Set parameters
|
andrewm@0
|
359 mapping->setName(controlName_);
|
andrewm@0
|
360 initializeMappingParameters(noteNumber, mapping);
|
andrewm@0
|
361
|
andrewm@0
|
362 // Save the mapping
|
andrewm@0
|
363 mappings_[noteNumber] = mapping;
|
andrewm@0
|
364
|
andrewm@0
|
365 // Finally, engage the new mapping
|
andrewm@0
|
366 mapping->engage();
|
andrewm@0
|
367 }
|
andrewm@0
|
368
|
andrewm@0
|
369 void removeMapping(int noteNumber) {
|
andrewm@0
|
370 // TODO: mutex
|
andrewm@0
|
371 if(mappings_.count(noteNumber) == 0)
|
andrewm@0
|
372 return;
|
andrewm@0
|
373 MappingType* mapping = mappings_[noteNumber];
|
andrewm@0
|
374 #ifdef NEW_MAPPING_SCHEDULER
|
andrewm@0
|
375 mapping->disengage(true);
|
andrewm@0
|
376 //keyboard_.mappingScheduler().unscheduleAndDelete(mapping);
|
andrewm@0
|
377 #else
|
andrewm@0
|
378 mapping->disengage();
|
andrewm@0
|
379 delete mapping;
|
andrewm@0
|
380 #endif
|
andrewm@0
|
381 mappings_.erase(noteNumber);
|
andrewm@0
|
382 }
|
andrewm@0
|
383
|
andrewm@0
|
384 protected:
|
andrewm@0
|
385 // State variables
|
andrewm@0
|
386 MidiKeyboardSegment& keyboardSegment_; // Segment of the keyboard that this mapping addresses
|
andrewm@0
|
387 OscMidiConverter *midiConverter_; // Object to convert OSC messages to MIDI
|
andrewm@0
|
388 std::map<int, MappingType*> mappings_; // Collection of active mappings
|
andrewm@0
|
389 CriticalSection mappingsMutex_; // Mutex protecting mappings from changes
|
andrewm@0
|
390
|
andrewm@0
|
391 std::string controlName_; // Name of the mapping
|
andrewm@0
|
392 float inputRangeMin_, inputRangeMax_; // Input ranges
|
andrewm@0
|
393 float inputRangeCenter_;
|
andrewm@0
|
394 int outOfRangeBehavior_; // What happens to out of range inputs
|
andrewm@0
|
395
|
andrewm@0
|
396 int midiControllerNumber_; // Which controller to use
|
andrewm@0
|
397 bool bypassed_; // Whether the mapping has been bypassed by UI
|
andrewm@0
|
398 unsigned int activeNotes_; // Indication of which notes out of the 12 to use
|
andrewm@0
|
399 };
|
andrewm@0
|
400
|
andrewm@0
|
401 #endif /* defined(__TouchKeys__TouchkeyBaseMappingFactory__) */ |