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@0
|
231 // ***** State Updaters *****
|
andrewm@0
|
232
|
andrewm@0
|
233 // These are called by PianoKey whenever certain events occur that might
|
andrewm@0
|
234 // merit the start and stop of a mapping. What is done with them depends on
|
andrewm@0
|
235 // the particular factory subclass.
|
andrewm@0
|
236
|
andrewm@0
|
237 // Touch becomes active on a key where it wasn't previously
|
andrewm@0
|
238 virtual void touchBegan(int noteNumber, bool midiNoteIsOn, bool keyMotionActive,
|
andrewm@0
|
239 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
240 Node<key_position>* positionBuffer,
|
andrewm@0
|
241 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
242 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
243 // Add a new mapping if one doesn't exist already
|
andrewm@0
|
244 if(mappings_.count(noteNumber) == 0) {
|
andrewm@0
|
245 #ifdef DEBUG_TOUCHKEY_BASE_MAPPING_FACTORY
|
andrewm@0
|
246 std::cout << "Note " << noteNumber << ": adding mapping (touch)\n";
|
andrewm@0
|
247 #endif
|
andrewm@0
|
248 int moduloNoteNumber = noteNumber % 12;
|
andrewm@0
|
249 if((activeNotes_ & (1 << moduloNoteNumber)) && !bypassed_)
|
andrewm@0
|
250 addMapping(noteNumber, touchBuffer, positionBuffer, positionTracker);
|
andrewm@0
|
251 }
|
andrewm@0
|
252 }
|
andrewm@0
|
253
|
andrewm@0
|
254 // Touch ends on a key where it wasn't previously
|
andrewm@0
|
255 virtual void touchEnded(int noteNumber, bool midiNoteIsOn, bool keyMotionActive,
|
andrewm@0
|
256 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
257 Node<key_position>* positionBuffer,
|
andrewm@0
|
258 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
259 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
260 // If a mapping exists but the MIDI note is off, remove the mapping
|
andrewm@0
|
261 if(mappings_.count(noteNumber) != 0 && !midiNoteIsOn) {
|
andrewm@0
|
262 #ifdef DEBUG_TOUCHKEY_BASE_MAPPING_FACTORY
|
andrewm@0
|
263 std::cout << "Note " << noteNumber << ": removing mapping (touch)\n";
|
andrewm@0
|
264 #endif
|
andrewm@0
|
265 if(mappings_[noteNumber]->requestFinish())
|
andrewm@0
|
266 removeMapping(noteNumber);
|
andrewm@0
|
267 }
|
andrewm@0
|
268 }
|
andrewm@0
|
269
|
andrewm@0
|
270 // MIDI note on for a key
|
andrewm@0
|
271 virtual void midiNoteOn(int noteNumber, bool touchIsOn, bool keyMotionActive,
|
andrewm@0
|
272 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
273 Node<key_position>* positionBuffer,
|
andrewm@0
|
274 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
275 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
276 // Add a new mapping if one doesn't exist already
|
andrewm@0
|
277 if(mappings_.count(noteNumber) == 0) {
|
andrewm@0
|
278 #ifdef DEBUG_TOUCHKEY_BASE_MAPPING_FACTORY
|
andrewm@0
|
279 std::cout << "Note " << noteNumber << ": adding mapping (MIDI)\n";
|
andrewm@0
|
280 #endif
|
andrewm@0
|
281 int moduloNoteNumber = noteNumber % 12;
|
andrewm@0
|
282 if((activeNotes_ & (1 << moduloNoteNumber)) && !bypassed_)
|
andrewm@0
|
283 addMapping(noteNumber, touchBuffer, positionBuffer, positionTracker);
|
andrewm@0
|
284 }
|
andrewm@0
|
285 }
|
andrewm@0
|
286
|
andrewm@0
|
287 // MIDI note off for a key
|
andrewm@0
|
288 virtual void midiNoteOff(int noteNumber, bool touchIsOn, bool keyMotionActive,
|
andrewm@0
|
289 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
290 Node<key_position>* positionBuffer,
|
andrewm@0
|
291 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
292 ScopedLock sl(mappingsMutex_);
|
andrewm@0
|
293 // If a mapping exists but the touch is off, remove the mapping
|
andrewm@0
|
294 if(mappings_.count(noteNumber) != 0 && !touchIsOn) {
|
andrewm@0
|
295 #ifdef DEBUG_TOUCHKEY_BASE_MAPPING_FACTORY
|
andrewm@0
|
296 std::cout << "Note " << noteNumber << ": removing mapping (MIDI)\n";
|
andrewm@0
|
297 #endif
|
andrewm@0
|
298 if(mappings_[noteNumber]->requestFinish())
|
andrewm@0
|
299 removeMapping(noteNumber);
|
andrewm@0
|
300 }
|
andrewm@0
|
301 }
|
andrewm@0
|
302
|
andrewm@0
|
303 // Subclasses of this one won't care about these two methods:
|
andrewm@0
|
304
|
andrewm@0
|
305 // Key goes active from continuous key position
|
andrewm@0
|
306 virtual void keyMotionActive(int noteNumber, bool midiNoteIsOn, bool touchIsOn,
|
andrewm@0
|
307 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
308 Node<key_position>* positionBuffer,
|
andrewm@0
|
309 KeyPositionTracker* positionTracker) {}
|
andrewm@0
|
310 // Key goes idle from continuous key position
|
andrewm@0
|
311 virtual void keyMotionIdle(int noteNumber, bool midiNoteIsOn, bool touchIsOn,
|
andrewm@0
|
312 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
313 Node<key_position>* positionBuffer,
|
andrewm@0
|
314 KeyPositionTracker* positionTracker) {}
|
andrewm@0
|
315
|
andrewm@0
|
316 // But we do use this one to send out default values:
|
andrewm@0
|
317 virtual void noteWillBegin(int noteNumber, int midiChannel, int midiVelocity) {
|
andrewm@0
|
318 if(midiConverter_ == 0)
|
andrewm@0
|
319 return;
|
andrewm@0
|
320 midiConverter_->clearLastValues(midiChannel, true);
|
andrewm@0
|
321 //midiConverter_->sendDefaultValue(midiChannel);
|
andrewm@0
|
322 }
|
andrewm@0
|
323
|
andrewm@0
|
324
|
andrewm@0
|
325 protected:
|
andrewm@0
|
326 // ***** Protected Methods *****
|
andrewm@0
|
327
|
andrewm@0
|
328 // This method should be set by the subclass to initialize the parameters of
|
andrewm@0
|
329 // a new mapping.
|
andrewm@0
|
330 virtual void initializeMappingParameters(int noteNumber, MappingType *mapping) {}
|
andrewm@0
|
331
|
andrewm@0
|
332 private:
|
andrewm@0
|
333 // ***** Private Methods *****
|
andrewm@0
|
334
|
andrewm@0
|
335 // Add a new mapping
|
andrewm@0
|
336 void addMapping(int noteNumber,
|
andrewm@0
|
337 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
338 Node<key_position>* positionBuffer,
|
andrewm@0
|
339 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
340 // TODO: mutex
|
andrewm@0
|
341 removeMapping(noteNumber); // Free any mapping that's already present on this note
|
andrewm@0
|
342
|
andrewm@0
|
343 MappingType *mapping = new MappingType(keyboard_, this, noteNumber, touchBuffer,
|
andrewm@0
|
344 positionBuffer, positionTracker);
|
andrewm@0
|
345
|
andrewm@0
|
346 // Set parameters
|
andrewm@0
|
347 mapping->setName(controlName_);
|
andrewm@0
|
348 initializeMappingParameters(noteNumber, mapping);
|
andrewm@0
|
349
|
andrewm@0
|
350 // Save the mapping
|
andrewm@0
|
351 mappings_[noteNumber] = mapping;
|
andrewm@0
|
352
|
andrewm@0
|
353 // Finally, engage the new mapping
|
andrewm@0
|
354 mapping->engage();
|
andrewm@0
|
355 }
|
andrewm@0
|
356
|
andrewm@0
|
357 void removeMapping(int noteNumber) {
|
andrewm@0
|
358 // TODO: mutex
|
andrewm@0
|
359 if(mappings_.count(noteNumber) == 0)
|
andrewm@0
|
360 return;
|
andrewm@0
|
361 MappingType* mapping = mappings_[noteNumber];
|
andrewm@0
|
362 #ifdef NEW_MAPPING_SCHEDULER
|
andrewm@0
|
363 mapping->disengage(true);
|
andrewm@0
|
364 //keyboard_.mappingScheduler().unscheduleAndDelete(mapping);
|
andrewm@0
|
365 #else
|
andrewm@0
|
366 mapping->disengage();
|
andrewm@0
|
367 delete mapping;
|
andrewm@0
|
368 #endif
|
andrewm@0
|
369 mappings_.erase(noteNumber);
|
andrewm@0
|
370 }
|
andrewm@0
|
371
|
andrewm@0
|
372 protected:
|
andrewm@0
|
373 // State variables
|
andrewm@0
|
374 MidiKeyboardSegment& keyboardSegment_; // Segment of the keyboard that this mapping addresses
|
andrewm@0
|
375 OscMidiConverter *midiConverter_; // Object to convert OSC messages to MIDI
|
andrewm@0
|
376 std::map<int, MappingType*> mappings_; // Collection of active mappings
|
andrewm@0
|
377 CriticalSection mappingsMutex_; // Mutex protecting mappings from changes
|
andrewm@0
|
378
|
andrewm@0
|
379 std::string controlName_; // Name of the mapping
|
andrewm@0
|
380 float inputRangeMin_, inputRangeMax_; // Input ranges
|
andrewm@0
|
381 float inputRangeCenter_;
|
andrewm@0
|
382 int outOfRangeBehavior_; // What happens to out of range inputs
|
andrewm@0
|
383
|
andrewm@0
|
384 int midiControllerNumber_; // Which controller to use
|
andrewm@0
|
385 bool bypassed_; // Whether the mapping has been bypassed by UI
|
andrewm@0
|
386 unsigned int activeNotes_; // Indication of which notes out of the 12 to use
|
andrewm@0
|
387 };
|
andrewm@0
|
388
|
andrewm@0
|
389 #endif /* defined(__TouchKeys__TouchkeyBaseMappingFactory__) */ |