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