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 TouchkeyControlMappingFactory.cpp: factory for the TouchKeys control
|
andrewm@0
|
21 mapping, which converts an arbitrary touch parameter into a MIDI or
|
andrewm@0
|
22 OSC control message.
|
andrewm@0
|
23 */
|
andrewm@0
|
24
|
andrewm@0
|
25 #include "TouchkeyControlMappingFactory.h"
|
andrewm@0
|
26 #include "TouchkeyControlMappingShortEditor.h"
|
andrewm@41
|
27 #include "TouchkeyControlMappingExtendedEditor.h"
|
andrewm@0
|
28
|
andrewm@0
|
29 const int TouchkeyControlMappingFactory::kDefaultController = 1;
|
andrewm@0
|
30 const float TouchkeyControlMappingFactory::kDefaultOutputRangeMin = 0.0;
|
andrewm@0
|
31 const float TouchkeyControlMappingFactory::kDefaultOutputRangeMax = 127.0;
|
andrewm@0
|
32 const float TouchkeyControlMappingFactory::kDefaultOutputDefault = 0.0;
|
andrewm@0
|
33
|
andrewm@0
|
34 TouchkeyControlMappingFactory::TouchkeyControlMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment) :
|
andrewm@0
|
35 TouchkeyBaseMappingFactory<TouchkeyControlMapping>(keyboard, segment),
|
andrewm@0
|
36 inputParameter_(TouchkeyControlMapping::kInputParameterYPosition),
|
andrewm@0
|
37 inputType_(TouchkeyControlMapping::kTypeAbsolute),
|
andrewm@0
|
38 outputRangeMin_(kDefaultOutputRangeMin), outputRangeMax_(kDefaultOutputRangeMax),
|
andrewm@0
|
39 outputDefault_(kDefaultOutputDefault), threshold_(0.0),
|
andrewm@0
|
40 ignoresTwoFingers_(TouchkeyControlMapping::kDefaultIgnoresTwoFingers),
|
andrewm@0
|
41 ignoresThreeFingers_(TouchkeyControlMapping::kDefaultIgnoresThreeFingers),
|
andrewm@0
|
42 direction_(TouchkeyControlMapping::kDefaultDirection)
|
andrewm@0
|
43 {
|
andrewm@0
|
44 setController(kDefaultController);
|
andrewm@0
|
45 }
|
andrewm@0
|
46
|
andrewm@0
|
47 // ***** Destructor *****
|
andrewm@0
|
48
|
andrewm@0
|
49 TouchkeyControlMappingFactory::~TouchkeyControlMappingFactory() {
|
andrewm@0
|
50
|
andrewm@0
|
51 }
|
andrewm@0
|
52
|
andrewm@0
|
53 // ***** Accessors / Modifiers *****
|
andrewm@0
|
54
|
andrewm@41
|
55 int TouchkeyControlMappingFactory::getDirection() {
|
andrewm@41
|
56 // Get the direction of motion. This is always positive for
|
andrewm@41
|
57 if(inputType_ == TouchkeyControlMapping::kTypeAbsolute)
|
andrewm@41
|
58 return TouchkeyControlMapping::kDirectionPositive;
|
andrewm@41
|
59 return direction_;
|
andrewm@41
|
60 }
|
andrewm@41
|
61
|
andrewm@0
|
62 void TouchkeyControlMappingFactory::setInputParameter(int inputParameter) {
|
andrewm@0
|
63 inputParameter_ = inputParameter;
|
andrewm@0
|
64 }
|
andrewm@0
|
65
|
andrewm@0
|
66 void TouchkeyControlMappingFactory::setInputType(int inputType) {
|
andrewm@0
|
67 inputType_ = inputType;
|
andrewm@0
|
68 }
|
andrewm@0
|
69
|
andrewm@0
|
70 void TouchkeyControlMappingFactory::setController(int controller) {
|
andrewm@0
|
71 // Before changing the controller, check if we were going to or from the pitch wheel.
|
andrewm@0
|
72 // If so, we should scale the value to or from a 14-bit value
|
andrewm@0
|
73 if(midiControllerNumber_ == MidiKeyboardSegment::kControlPitchWheel &&
|
andrewm@0
|
74 controller != MidiKeyboardSegment::kControlPitchWheel) {
|
andrewm@0
|
75 outputRangeMax_ = outputRangeMax_ / 128.0;
|
andrewm@0
|
76 if(outputRangeMax_ > 127.0)
|
andrewm@0
|
77 outputRangeMax_ = 127.0;
|
andrewm@0
|
78 outputRangeMin_ = outputRangeMin_ / 128.0;
|
andrewm@0
|
79 if(outputRangeMin_ > 127.0)
|
andrewm@0
|
80 outputRangeMin_ = 127.0;
|
andrewm@0
|
81 outputDefault_ = outputDefault_ / 128.0;
|
andrewm@0
|
82 if(outputDefault_ > 127.0)
|
andrewm@0
|
83 outputDefault_ = 127.0;
|
andrewm@0
|
84 }
|
andrewm@0
|
85 else if(midiControllerNumber_ != MidiKeyboardSegment::kControlPitchWheel &&
|
andrewm@0
|
86 controller == MidiKeyboardSegment::kControlPitchWheel) {
|
andrewm@0
|
87 if(outputRangeMax_ == 127.0)
|
andrewm@0
|
88 outputRangeMax_ = 16383.0;
|
andrewm@0
|
89 else
|
andrewm@0
|
90 outputRangeMax_ = outputRangeMax_ * 128.0;
|
andrewm@0
|
91 if(outputRangeMin_ == 127.0)
|
andrewm@0
|
92 outputRangeMin_ = 16383.0;
|
andrewm@0
|
93 else
|
andrewm@0
|
94 outputRangeMin_ = outputRangeMin_ * 128.0;
|
andrewm@0
|
95 if(outputDefault_ == 127.0)
|
andrewm@0
|
96 outputDefault_ = 16383.0;
|
andrewm@0
|
97 else
|
andrewm@0
|
98 outputDefault_ = outputDefault_ * 128.0;
|
andrewm@0
|
99 }
|
andrewm@0
|
100
|
andrewm@0
|
101 setMidiParameters(controller, inputRangeMin_, inputRangeMax_, inputRangeCenter_,
|
andrewm@41
|
102 outputDefault_, outputRangeMin_, outputRangeMax_,
|
andrewm@41
|
103 -1, use14BitControl_, outOfRangeBehavior_);
|
andrewm@0
|
104
|
andrewm@0
|
105 // Listen to incoming controls from the keyboard too, if this is enabled
|
andrewm@0
|
106 // in MidiKeyboardSegment
|
andrewm@0
|
107 if(midiConverter_ != 0) {
|
andrewm@0
|
108 midiConverter_->listenToIncomingControl(midiControllerNumber_);
|
andrewm@0
|
109 }
|
andrewm@0
|
110 }
|
andrewm@0
|
111
|
andrewm@0
|
112 void TouchkeyControlMappingFactory::setRangeInputMin(float inputMin) {
|
andrewm@0
|
113 if(inputMin < -1.0)
|
andrewm@0
|
114 inputRangeMin_ = -1.0;
|
andrewm@0
|
115 else if(inputMin > 1.0)
|
andrewm@0
|
116 inputRangeMin_ = 1.0;
|
andrewm@0
|
117 else
|
andrewm@0
|
118 inputRangeMin_ = inputMin;
|
andrewm@0
|
119
|
andrewm@0
|
120 // Update control
|
andrewm@0
|
121 //if(midiConverter_ == 0)
|
andrewm@0
|
122 // return;
|
andrewm@0
|
123 //midiConverter_->setControlMinValue(controlName_.c_str(), inputRangeMin_);
|
andrewm@0
|
124 setMidiParameters(midiControllerNumber_, inputRangeMin_, inputRangeMax_, inputRangeCenter_,
|
andrewm@41
|
125 outputDefault_, outputRangeMin_, outputRangeMax_,
|
andrewm@41
|
126 -1, use14BitControl_, outOfRangeBehavior_);
|
andrewm@0
|
127 }
|
andrewm@0
|
128
|
andrewm@0
|
129 void TouchkeyControlMappingFactory::setRangeInputMax(float inputMax) {
|
andrewm@0
|
130 if(inputMax < -1.0)
|
andrewm@0
|
131 inputRangeMax_ = -1.0;
|
andrewm@0
|
132 else if(inputMax > 1.0)
|
andrewm@0
|
133 inputRangeMax_ = 1.0;
|
andrewm@0
|
134 else
|
andrewm@0
|
135 inputRangeMax_ = inputMax;
|
andrewm@0
|
136
|
andrewm@0
|
137 // Update control
|
andrewm@0
|
138 //if(midiConverter_ == 0)
|
andrewm@0
|
139 // return;
|
andrewm@0
|
140 //midiConverter_->setControlMaxValue(controlName_.c_str(), inputRangeMax_);
|
andrewm@0
|
141 setMidiParameters(midiControllerNumber_, inputRangeMin_, inputRangeMax_, inputRangeCenter_,
|
andrewm@41
|
142 outputDefault_, outputRangeMin_, outputRangeMax_,
|
andrewm@41
|
143 -1, use14BitControl_, outOfRangeBehavior_);
|
andrewm@0
|
144 }
|
andrewm@0
|
145
|
andrewm@0
|
146 void TouchkeyControlMappingFactory::setRangeInputCenter(float inputCenter) {
|
andrewm@0
|
147 if(inputCenter < -1.0)
|
andrewm@0
|
148 inputRangeCenter_ = -1.0;
|
andrewm@0
|
149 else if(inputCenter > 1.0)
|
andrewm@0
|
150 inputRangeCenter_ = 1.0;
|
andrewm@0
|
151 else
|
andrewm@0
|
152 inputRangeCenter_ = inputCenter;
|
andrewm@0
|
153
|
andrewm@0
|
154 // Update control
|
andrewm@0
|
155 //if(midiConverter_ == 0)
|
andrewm@0
|
156 // return;
|
andrewm@0
|
157 //midiConverter_->setControlCenterValue(controlName_.c_str(), inputRangeCenter_);
|
andrewm@0
|
158 setMidiParameters(midiControllerNumber_, inputRangeMin_, inputRangeMax_, inputRangeCenter_,
|
andrewm@41
|
159 outputDefault_, outputRangeMin_, outputRangeMax_,
|
andrewm@41
|
160 -1, use14BitControl_, outOfRangeBehavior_);
|
andrewm@0
|
161 }
|
andrewm@0
|
162
|
andrewm@0
|
163 void TouchkeyControlMappingFactory::setRangeOutputMin(float outputMin) {
|
andrewm@0
|
164 outputRangeMin_ = outputMin;
|
andrewm@0
|
165
|
andrewm@0
|
166 setMidiParameters(midiControllerNumber_, inputRangeMin_, inputRangeMax_, inputRangeCenter_,
|
andrewm@41
|
167 outputDefault_, outputRangeMin_, outputRangeMax_,
|
andrewm@41
|
168 -1, use14BitControl_, outOfRangeBehavior_);
|
andrewm@0
|
169 }
|
andrewm@0
|
170
|
andrewm@0
|
171 void TouchkeyControlMappingFactory::setRangeOutputMax(float outputMax) {
|
andrewm@0
|
172 outputRangeMax_ = outputMax;
|
andrewm@0
|
173
|
andrewm@0
|
174 setMidiParameters(midiControllerNumber_, inputRangeMin_, inputRangeMax_, inputRangeCenter_,
|
andrewm@41
|
175 outputDefault_, outputRangeMin_, outputRangeMax_,
|
andrewm@41
|
176 -1, use14BitControl_, outOfRangeBehavior_);
|
andrewm@0
|
177 }
|
andrewm@0
|
178
|
andrewm@0
|
179 void TouchkeyControlMappingFactory::setRangeOutputDefault(float outputDefault) {
|
andrewm@0
|
180 outputDefault_ = outputDefault;
|
andrewm@0
|
181
|
andrewm@0
|
182 setMidiParameters(midiControllerNumber_, inputRangeMin_, inputRangeMax_, inputRangeCenter_,
|
andrewm@41
|
183 outputDefault_, outputRangeMin_, outputRangeMax_,
|
andrewm@41
|
184 -1, use14BitControl_, outOfRangeBehavior_);
|
andrewm@0
|
185 }
|
andrewm@0
|
186
|
andrewm@0
|
187 void TouchkeyControlMappingFactory::setThreshold(float threshold) {
|
andrewm@0
|
188 threshold_ = threshold;
|
andrewm@0
|
189 }
|
andrewm@0
|
190
|
andrewm@0
|
191 void TouchkeyControlMappingFactory::setIgnoresTwoFingers(bool ignoresTwo) {
|
andrewm@0
|
192 ignoresTwoFingers_ = ignoresTwo;
|
andrewm@0
|
193 }
|
andrewm@0
|
194
|
andrewm@0
|
195 void TouchkeyControlMappingFactory::setIgnoresThreeFingers(bool ignoresThree) {
|
andrewm@0
|
196 ignoresThreeFingers_ = ignoresThree;
|
andrewm@0
|
197 }
|
andrewm@0
|
198
|
andrewm@0
|
199 void TouchkeyControlMappingFactory::setDirection(int direction) {
|
andrewm@0
|
200 direction_ = direction;
|
andrewm@0
|
201 }
|
andrewm@0
|
202
|
andrewm@41
|
203 void TouchkeyControlMappingFactory::setOutOfRangeBehavior(int behavior) {
|
andrewm@41
|
204 outOfRangeBehavior_ = behavior;
|
andrewm@41
|
205
|
andrewm@41
|
206 setMidiParameters(midiControllerNumber_, inputRangeMin_, inputRangeMax_, inputRangeCenter_,
|
andrewm@41
|
207 outputDefault_, outputRangeMin_, outputRangeMax_,
|
andrewm@41
|
208 -1, use14BitControl_, outOfRangeBehavior_);
|
andrewm@41
|
209 }
|
andrewm@41
|
210
|
andrewm@41
|
211 void TouchkeyControlMappingFactory::setUses14BitControl(bool use) {
|
andrewm@41
|
212 use14BitControl_ = use;
|
andrewm@41
|
213
|
andrewm@41
|
214 setMidiParameters(midiControllerNumber_, inputRangeMin_, inputRangeMax_, inputRangeCenter_,
|
andrewm@41
|
215 outputDefault_, outputRangeMin_, outputRangeMax_,
|
andrewm@41
|
216 -1, use14BitControl_, outOfRangeBehavior_);
|
andrewm@41
|
217 }
|
andrewm@41
|
218
|
andrewm@0
|
219 // ***** GUI Support *****
|
andrewm@0
|
220 MappingEditorComponent* TouchkeyControlMappingFactory::createBasicEditor() {
|
andrewm@0
|
221 return new TouchkeyControlMappingShortEditor(*this);
|
andrewm@0
|
222 }
|
andrewm@0
|
223
|
andrewm@41
|
224 MappingEditorComponent* TouchkeyControlMappingFactory::createExtendedEditor() {
|
andrewm@41
|
225 return new TouchkeyControlMappingExtendedEditor(*this);
|
andrewm@41
|
226 }
|
andrewm@41
|
227
|
andrewm@41
|
228
|
andrewm@33
|
229 // ****** Preset Save/Load ******
|
andrewm@33
|
230 XmlElement* TouchkeyControlMappingFactory::getPreset() {
|
andrewm@34
|
231 PropertySet properties;
|
andrewm@34
|
232
|
andrewm@34
|
233 storeCommonProperties(properties);
|
andrewm@34
|
234 properties.setValue("inputParameter", inputParameter_);
|
andrewm@34
|
235 properties.setValue("inputType", inputType_);
|
andrewm@34
|
236 properties.setValue("outputRangeMin", outputRangeMin_);
|
andrewm@34
|
237 properties.setValue("outputRangeMax", outputRangeMax_);
|
andrewm@34
|
238 properties.setValue("outputDefault", outputDefault_);
|
andrewm@34
|
239 properties.setValue("threshold", threshold_);
|
andrewm@34
|
240 properties.setValue("ignoresTwoFingers", ignoresTwoFingers_);
|
andrewm@34
|
241 properties.setValue("ignoresThreeFingers", ignoresThreeFingers_);
|
andrewm@34
|
242 properties.setValue("direction", direction_);
|
andrewm@43
|
243 properties.setValue("use14Bit", use14BitControl_);
|
andrewm@34
|
244
|
andrewm@34
|
245 XmlElement* preset = properties.createXml("MappingFactory");
|
andrewm@33
|
246 preset->setAttribute("type", "Control");
|
andrewm@34
|
247
|
andrewm@33
|
248 return preset;
|
andrewm@33
|
249 }
|
andrewm@33
|
250
|
andrewm@33
|
251 bool TouchkeyControlMappingFactory::loadPreset(XmlElement const* preset) {
|
andrewm@34
|
252 if(preset == 0)
|
andrewm@34
|
253 return false;
|
andrewm@34
|
254
|
andrewm@34
|
255 PropertySet properties;
|
andrewm@34
|
256 properties.restoreFromXml(*preset);
|
andrewm@34
|
257
|
andrewm@34
|
258 if(!loadCommonProperties(properties))
|
andrewm@34
|
259 return false;
|
andrewm@34
|
260 if(!properties.containsKey("inputParameter") ||
|
andrewm@34
|
261 !properties.containsKey("inputType") ||
|
andrewm@34
|
262 !properties.containsKey("outputRangeMin") ||
|
andrewm@34
|
263 !properties.containsKey("outputRangeMax") ||
|
andrewm@34
|
264 !properties.containsKey("outputDefault") ||
|
andrewm@34
|
265 !properties.containsKey("threshold") ||
|
andrewm@34
|
266 !properties.containsKey("ignoresTwoFingers") ||
|
andrewm@34
|
267 !properties.containsKey("ignoresThreeFingers") ||
|
andrewm@34
|
268 !properties.containsKey("direction"))
|
andrewm@34
|
269 return false;
|
andrewm@34
|
270
|
andrewm@34
|
271 inputParameter_ = properties.getIntValue("inputParameter");
|
andrewm@34
|
272 inputType_ = properties.getIntValue("inputType");
|
andrewm@35
|
273 outputRangeMin_ = properties.getDoubleValue("outputRangeMin");
|
andrewm@35
|
274 outputRangeMax_ = properties.getDoubleValue("outputRangeMax");
|
andrewm@35
|
275 outputDefault_ = properties.getDoubleValue("outputDefault");
|
andrewm@35
|
276 threshold_ = properties.getDoubleValue("threshold");
|
andrewm@35
|
277 ignoresTwoFingers_ = properties.getBoolValue("ignoresTwoFingers");
|
andrewm@35
|
278 ignoresThreeFingers_ = properties.getBoolValue("ignoresThreeFingers");
|
andrewm@34
|
279 direction_ = properties.getIntValue("direction");
|
andrewm@34
|
280
|
andrewm@43
|
281 // These values added to later versions of the presets so check
|
andrewm@43
|
282 // whether they actually exist or not
|
andrewm@43
|
283 if(properties.containsKey("use14Bit"))
|
andrewm@43
|
284 use14BitControl_ = properties.getBoolValue("use14Bit");
|
andrewm@43
|
285
|
andrewm@34
|
286 // Update MIDI information; this doesn't actually change the controller
|
andrewm@34
|
287 // (which is already set) but it adds a listener and updates the ranges
|
andrewm@34
|
288 setController(midiControllerNumber_);
|
andrewm@34
|
289
|
andrewm@33
|
290 return true;
|
andrewm@33
|
291 }
|
andrewm@33
|
292
|
andrewm@0
|
293 // ***** Private Methods *****
|
andrewm@0
|
294
|
andrewm@0
|
295 void TouchkeyControlMappingFactory::initializeMappingParameters(int noteNumber, TouchkeyControlMapping *mapping) {
|
andrewm@0
|
296 // Set parameters
|
andrewm@0
|
297 mapping->setInputParameter(inputParameter_, inputType_);
|
andrewm@0
|
298 mapping->setRange(inputRangeMin_, inputRangeMax_, outputRangeMin_, outputRangeMax_, outputDefault_);
|
andrewm@0
|
299 mapping->setThreshold(threshold_);
|
andrewm@0
|
300 mapping->setIgnoresMultipleFingers(ignoresTwoFingers_, ignoresThreeFingers_);
|
andrewm@0
|
301 mapping->setDirection(direction_);
|
andrewm@0
|
302 }
|