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 MappingFactorySplitter.cpp: MappingFactory subclass which in turn contains
|
andrewm@0
|
21 several factories, routing all incoming method calls to each of them.
|
andrewm@0
|
22 */
|
andrewm@0
|
23
|
andrewm@0
|
24 #include "MappingFactorySplitter.h"
|
andrewm@0
|
25
|
andrewm@0
|
26 // Look up a mapping with the given note number
|
andrewm@0
|
27 Mapping* MappingFactorySplitter::mapping(int noteNumber) {
|
andrewm@0
|
28 // TODO: find a mapping in any of the factories
|
andrewm@0
|
29 if(factories_.empty())
|
andrewm@0
|
30 return 0;
|
andrewm@0
|
31 return (*factories_.begin())->mapping(noteNumber);
|
andrewm@0
|
32 }
|
andrewm@0
|
33
|
andrewm@0
|
34 // Return a list of all active notes
|
andrewm@0
|
35 std::vector<int> MappingFactorySplitter::activeMappings() {
|
andrewm@0
|
36 // TODO: merge all active factories
|
andrewm@0
|
37 if(factories_.empty()) {
|
andrewm@0
|
38 return std::vector<int>();
|
andrewm@0
|
39 }
|
andrewm@0
|
40 return (*factories_.begin())->activeMappings();
|
andrewm@0
|
41 }
|
andrewm@0
|
42
|
andrewm@0
|
43 // Remove all active mappings
|
andrewm@0
|
44 void MappingFactorySplitter::removeAllMappings() {
|
andrewm@0
|
45 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
46
|
andrewm@0
|
47 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
48 (*it)->removeAllMappings();
|
andrewm@0
|
49 }
|
andrewm@0
|
50 }
|
andrewm@0
|
51
|
andrewm@0
|
52 // Suspend messages from a particular note
|
andrewm@0
|
53 void MappingFactorySplitter::suspendMapping(int noteNumber) {
|
andrewm@0
|
54 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
55
|
andrewm@0
|
56 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
57 (*it)->suspendMapping(noteNumber);
|
andrewm@0
|
58 }
|
andrewm@0
|
59 }
|
andrewm@0
|
60
|
andrewm@0
|
61 // Suspend messages from all notes
|
andrewm@0
|
62 void MappingFactorySplitter::suspendAllMappings() {
|
andrewm@0
|
63 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
64
|
andrewm@0
|
65 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
66 (*it)->suspendAllMappings();
|
andrewm@0
|
67 }
|
andrewm@0
|
68 }
|
andrewm@0
|
69
|
andrewm@0
|
70 // Resume messages from a particular note
|
andrewm@0
|
71 void MappingFactorySplitter::resumeMapping(int noteNumber, bool resend) {
|
andrewm@0
|
72 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
73
|
andrewm@0
|
74 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
75 (*it)->resumeMapping(noteNumber, resend);
|
andrewm@0
|
76 }
|
andrewm@0
|
77 }
|
andrewm@0
|
78
|
andrewm@0
|
79 // Resume messages from all notes
|
andrewm@0
|
80 void MappingFactorySplitter::resumeAllMappings(bool resend) {
|
andrewm@0
|
81 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
82
|
andrewm@0
|
83 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
84 (*it)->resumeAllMappings(resend);
|
andrewm@0
|
85 }
|
andrewm@0
|
86 }
|
andrewm@0
|
87
|
andrewm@0
|
88 // Whether the component parts of this mapping are bypassed
|
andrewm@0
|
89 int MappingFactorySplitter::bypassed() {
|
andrewm@0
|
90 if(factories_.empty())
|
andrewm@0
|
91 return bypassNewMappings_;
|
andrewm@0
|
92 bool bypassOn = false, bypassOff = false;
|
andrewm@0
|
93
|
andrewm@0
|
94 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
95 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
96 if((*it)->bypassed())
|
andrewm@0
|
97 bypassOn = true;
|
andrewm@0
|
98 else
|
andrewm@0
|
99 bypassOff = true;
|
andrewm@0
|
100 }
|
andrewm@0
|
101
|
andrewm@0
|
102 // Three states: all on, all off, or some on + some off (mixed)
|
andrewm@0
|
103 if(bypassOn && !bypassOff)
|
andrewm@0
|
104 return kBypassOn;
|
andrewm@0
|
105 if(bypassOff && !bypassOn)
|
andrewm@0
|
106 return kBypassOff;
|
andrewm@0
|
107 return kBypassMixed;
|
andrewm@0
|
108 }
|
andrewm@0
|
109
|
andrewm@0
|
110 // Set whether the component parts are bypassed
|
andrewm@0
|
111 void MappingFactorySplitter::setBypassed(bool bypass) {
|
andrewm@0
|
112 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
113 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
114 (*it)->setBypassed(bypass);
|
andrewm@0
|
115 }
|
andrewm@0
|
116 bypassNewMappings_ = bypass;
|
andrewm@0
|
117 }
|
andrewm@0
|
118
|
andrewm@0
|
119 // Add a factory to the list
|
andrewm@0
|
120 void MappingFactorySplitter::addFactory(MappingFactory* factory) {
|
andrewm@0
|
121 if(bypassNewMappings_)
|
andrewm@0
|
122 factory->setBypassed(true);
|
andrewm@0
|
123 factories_.push_back(factory);
|
andrewm@0
|
124 }
|
andrewm@0
|
125
|
andrewm@0
|
126 // Remove a factory from the list
|
andrewm@0
|
127 void MappingFactorySplitter::removeFactory(MappingFactory* factory) {
|
andrewm@0
|
128 // Assume allocation/deallocation takes place elsewhere
|
andrewm@0
|
129 std::list<MappingFactory*>::iterator it = factories_.begin();
|
andrewm@0
|
130
|
andrewm@0
|
131 while(it != factories_.end()) {
|
andrewm@0
|
132 if(*it == factory)
|
andrewm@0
|
133 factories_.erase(it++);
|
andrewm@0
|
134 else
|
andrewm@0
|
135 it++;
|
andrewm@0
|
136 }
|
andrewm@0
|
137 }
|
andrewm@0
|
138
|
andrewm@0
|
139 // Remove all factories from the list
|
andrewm@0
|
140 void MappingFactorySplitter::removeAllFactories() {
|
andrewm@0
|
141 // Assume allocation/deallocation takes place elsewhere
|
andrewm@0
|
142 factories_.clear();
|
andrewm@0
|
143 }
|
andrewm@0
|
144
|
andrewm@33
|
145 // Generate XML element with preset settings
|
andrewm@33
|
146 XmlElement* MappingFactorySplitter::getPreset() {
|
andrewm@33
|
147 XmlElement *preset = new XmlElement("MappingFactory");
|
andrewm@33
|
148 preset->setAttribute("type", "Splitter");
|
andrewm@33
|
149 return preset;
|
andrewm@33
|
150 }
|
andrewm@33
|
151
|
andrewm@33
|
152 bool MappingFactorySplitter::loadPreset(XmlElement const* preset) {
|
andrewm@33
|
153 return true;
|
andrewm@33
|
154 }
|
andrewm@33
|
155
|
andrewm@0
|
156 // Touch becomes active on a key where it wasn't previously
|
andrewm@0
|
157 void MappingFactorySplitter::touchBegan(int noteNumber, bool midiNoteIsOn, bool keyMotionActive,
|
andrewm@0
|
158 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
159 Node<key_position>* positionBuffer,
|
andrewm@0
|
160 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
161 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
162
|
andrewm@0
|
163 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
164 (*it)->touchBegan(noteNumber, midiNoteIsOn, keyMotionActive,
|
andrewm@0
|
165 touchBuffer, positionBuffer, positionTracker);
|
andrewm@0
|
166 }
|
andrewm@0
|
167 }
|
andrewm@0
|
168
|
andrewm@0
|
169 // Touch ends on a key where it wasn't previously
|
andrewm@0
|
170 void MappingFactorySplitter::touchEnded(int noteNumber, bool midiNoteIsOn, bool keyMotionActive,
|
andrewm@0
|
171 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
172 Node<key_position>* positionBuffer,
|
andrewm@0
|
173 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
174 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
175
|
andrewm@0
|
176 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
177 (*it)->touchEnded(noteNumber, midiNoteIsOn, keyMotionActive,
|
andrewm@0
|
178 touchBuffer, positionBuffer, positionTracker);
|
andrewm@0
|
179 }
|
andrewm@0
|
180 }
|
andrewm@0
|
181
|
andrewm@0
|
182 // MIDI note on for a key
|
andrewm@0
|
183 void MappingFactorySplitter::midiNoteOn(int noteNumber, bool touchIsOn, bool keyMotionActive,
|
andrewm@0
|
184 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
185 Node<key_position>* positionBuffer,
|
andrewm@0
|
186 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
187
|
andrewm@0
|
188 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
189
|
andrewm@0
|
190 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
191 (*it)->midiNoteOn(noteNumber, touchIsOn, keyMotionActive,
|
andrewm@0
|
192 touchBuffer, positionBuffer, positionTracker);
|
andrewm@0
|
193 }
|
andrewm@0
|
194 }
|
andrewm@0
|
195
|
andrewm@0
|
196 // MIDI note off for a key
|
andrewm@0
|
197 void MappingFactorySplitter::midiNoteOff(int noteNumber, bool touchIsOn, bool keyMotionActive,
|
andrewm@0
|
198 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
199 Node<key_position>* positionBuffer,
|
andrewm@0
|
200 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
201 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
202
|
andrewm@0
|
203 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
204 (*it)->midiNoteOff(noteNumber, touchIsOn, keyMotionActive,
|
andrewm@0
|
205 touchBuffer, positionBuffer, positionTracker);
|
andrewm@0
|
206 }
|
andrewm@0
|
207 }
|
andrewm@0
|
208
|
andrewm@0
|
209 // Key goes active from continuous key position
|
andrewm@0
|
210 void MappingFactorySplitter::keyMotionActive(int noteNumber, bool midiNoteIsOn, bool touchIsOn,
|
andrewm@0
|
211 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
212 Node<key_position>* positionBuffer,
|
andrewm@0
|
213 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
214 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
215
|
andrewm@0
|
216 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
217 (*it)->keyMotionActive(noteNumber, midiNoteIsOn, touchIsOn,
|
andrewm@0
|
218 touchBuffer, positionBuffer, positionTracker);
|
andrewm@0
|
219 }
|
andrewm@0
|
220 }
|
andrewm@0
|
221
|
andrewm@0
|
222 // Key goes idle from continuous key position
|
andrewm@0
|
223 void MappingFactorySplitter::keyMotionIdle(int noteNumber, bool midiNoteIsOn, bool touchIsOn,
|
andrewm@0
|
224 Node<KeyTouchFrame>* touchBuffer,
|
andrewm@0
|
225 Node<key_position>* positionBuffer,
|
andrewm@0
|
226 KeyPositionTracker* positionTracker) {
|
andrewm@0
|
227 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
228
|
andrewm@0
|
229 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
230 (*it)->keyMotionIdle(noteNumber, midiNoteIsOn, touchIsOn,
|
andrewm@0
|
231 touchBuffer, positionBuffer, positionTracker);
|
andrewm@0
|
232 }
|
andrewm@0
|
233 }
|
andrewm@0
|
234
|
andrewm@0
|
235 // MIDI note about to begin
|
andrewm@0
|
236 void MappingFactorySplitter::noteWillBegin(int noteNumber, int midiChannel, int midiVelocity) {
|
andrewm@0
|
237 std::list<MappingFactory*>::iterator it;
|
andrewm@0
|
238
|
andrewm@0
|
239 for(it = factories_.begin(); it != factories_.end(); ++it) {
|
andrewm@0
|
240 (*it)->noteWillBegin(noteNumber, midiChannel, midiVelocity);
|
andrewm@0
|
241 }
|
andrewm@0
|
242 } |