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 MidiInputController.cpp: handles incoming MIDI data and manages input
|
andrewm@0
|
21 ports. Detailed processing is broken down by keyboard segment; see
|
andrewm@0
|
22 MidiKeyboardSegment.h/cpp for more.
|
andrewm@0
|
23 */
|
andrewm@0
|
24
|
andrewm@0
|
25
|
andrewm@0
|
26 #include "MidiInputController.h"
|
andrewm@0
|
27 #include "MidiOutputController.h"
|
andrewm@0
|
28 #include "../Mappings/MappingFactory.h"
|
andrewm@0
|
29
|
andrewm@33
|
30 #undef DEBUG_MIDI_INPUT_CONTROLLER
|
andrewm@0
|
31 #undef MIDI_INPUT_CONTROLLER_DEBUG_RAW
|
andrewm@0
|
32
|
andrewm@0
|
33 // Constructor
|
andrewm@0
|
34
|
andrewm@0
|
35 MidiInputController::MidiInputController(PianoKeyboard& keyboard)
|
andrewm@31
|
36 : keyboard_(keyboard), midiOutputController_(0), primaryActivePort_(-1),
|
andrewm@31
|
37 segmentUniqueIdentifier_(0)
|
andrewm@0
|
38 {
|
andrewm@0
|
39 logFileCreated = false;
|
andrewm@0
|
40 loggingActive = false;
|
andrewm@0
|
41
|
andrewm@0
|
42 }
|
andrewm@0
|
43
|
andrewm@0
|
44 void MidiInputController::setMidiOutputController(MidiOutputController* ct) {
|
andrewm@0
|
45 midiOutputController_ = ct;
|
andrewm@0
|
46
|
andrewm@0
|
47 // Propagate the change to the keyboard segments
|
andrewm@0
|
48 ScopedLock sl(segmentsMutex_);
|
andrewm@0
|
49 for(int i = 0; i < segments_.size(); i++) {
|
andrewm@0
|
50 segments_[i]->setMidiOutputController(ct);
|
andrewm@0
|
51 }
|
andrewm@0
|
52 }
|
andrewm@0
|
53
|
andrewm@0
|
54 // ------------------------------------------------------
|
andrewm@0
|
55 // create a new MIDI log file, ready to have data written to it
|
andrewm@0
|
56 void MidiInputController::createLogFile(string midiLog_filename, string path)
|
andrewm@0
|
57 {
|
andrewm@0
|
58 // indicate that we have created a log file (so we can close it later)
|
andrewm@0
|
59 logFileCreated = true;
|
andrewm@0
|
60
|
andrewm@0
|
61 if (path.compare("") != 0)
|
andrewm@0
|
62 {
|
andrewm@0
|
63 path = path + "/";
|
andrewm@0
|
64 }
|
andrewm@0
|
65
|
andrewm@0
|
66 midiLog_filename = path + midiLog_filename;
|
andrewm@0
|
67
|
andrewm@0
|
68 char *fileName = (char*)midiLog_filename.c_str();
|
andrewm@0
|
69
|
andrewm@0
|
70 // create output file
|
andrewm@0
|
71 midiLog.open (fileName, ios::out | ios::binary);
|
andrewm@0
|
72 midiLog.seekp(0);
|
andrewm@0
|
73 }
|
andrewm@0
|
74
|
andrewm@0
|
75 // ------------------------------------------------------
|
andrewm@0
|
76 // close the existing log file
|
andrewm@0
|
77 void MidiInputController::closeLogFile()
|
andrewm@0
|
78 {
|
andrewm@0
|
79 if (logFileCreated)
|
andrewm@0
|
80 {
|
andrewm@0
|
81 midiLog.close();
|
andrewm@0
|
82 logFileCreated = false;
|
andrewm@0
|
83 }
|
andrewm@0
|
84 }
|
andrewm@0
|
85
|
andrewm@0
|
86 // ------------------------------------------------------
|
andrewm@0
|
87 // start logging midi data
|
andrewm@0
|
88 void MidiInputController::startLogging()
|
andrewm@0
|
89 {
|
andrewm@0
|
90 loggingActive = true;
|
andrewm@0
|
91 }
|
andrewm@0
|
92
|
andrewm@0
|
93 // ------------------------------------------------------
|
andrewm@0
|
94 // stop logging midi data
|
andrewm@0
|
95 void MidiInputController::stopLogging()
|
andrewm@0
|
96 {
|
andrewm@0
|
97 loggingActive = false;
|
andrewm@0
|
98 }
|
andrewm@0
|
99
|
andrewm@0
|
100 // Iterate through the available MIDI devices. Return a vector containing
|
andrewm@0
|
101 // indices and names for each device. The index will later be passed back
|
andrewm@0
|
102 // to indicate which device to open.
|
andrewm@0
|
103
|
andrewm@0
|
104 vector<pair<int, string> > MidiInputController::availableMidiDevices() {
|
andrewm@0
|
105 vector<pair<int, string> > deviceList;
|
andrewm@0
|
106
|
andrewm@0
|
107 try {
|
andrewm@0
|
108 StringArray deviceStrings = MidiInput::getDevices();
|
andrewm@0
|
109
|
andrewm@0
|
110 for(int i = 0; i < deviceStrings.size(); i++) {
|
andrewm@0
|
111 pair<int, string> p(i, string(deviceStrings[i].toUTF8()));
|
andrewm@0
|
112 deviceList.push_back(p);
|
andrewm@0
|
113 }
|
andrewm@0
|
114 }
|
andrewm@0
|
115 catch(...) {
|
andrewm@0
|
116 deviceList.clear();
|
andrewm@0
|
117 }
|
andrewm@0
|
118
|
andrewm@0
|
119 return deviceList;
|
andrewm@0
|
120 }
|
andrewm@0
|
121
|
andrewm@0
|
122 // Enable a new MIDI port according to its index (returned from availableMidiDevices())
|
andrewm@0
|
123 // Returns true on success.
|
andrewm@0
|
124
|
andrewm@31
|
125 bool MidiInputController::enablePort(int portNumber, bool isPrimary) {
|
andrewm@0
|
126 if(portNumber < 0)
|
andrewm@0
|
127 return false;
|
andrewm@31
|
128 // If this is already the primary port, nothing to do
|
andrewm@31
|
129 if(isPrimary && primaryActivePort_ == portNumber)
|
andrewm@31
|
130 return true;
|
andrewm@31
|
131
|
andrewm@31
|
132 // If this port is active already but we are not making it primary,
|
andrewm@31
|
133 // then fail: can't override primary with aux
|
andrewm@31
|
134 if(!isPrimary)
|
andrewm@31
|
135 if(activePorts_.count(portNumber) > 0)
|
andrewm@31
|
136 return false;
|
andrewm@0
|
137
|
andrewm@31
|
138 // If there is already a (different) primary active port, disable it
|
andrewm@31
|
139 if(isPrimary && primaryActivePort_ >= 0 && activePorts_.count(primaryActivePort_) > 0)
|
andrewm@31
|
140 disablePort(primaryActivePort_);
|
andrewm@31
|
141
|
andrewm@31
|
142 // Enable the port if it hasn't been already
|
andrewm@31
|
143 if(activePorts_.count(portNumber) == 0) {
|
andrewm@31
|
144 MidiInput *device = MidiInput::openDevice(portNumber, this);
|
andrewm@31
|
145
|
andrewm@31
|
146 if(device == 0) {
|
andrewm@31
|
147 #ifdef DEBUG_MIDI_INPUT_CONTROLLER
|
andrewm@31
|
148 cout << "Failed to enable MIDI input port " << portNumber << ")\n";
|
andrewm@31
|
149 #endif
|
andrewm@31
|
150 return false;
|
andrewm@31
|
151 }
|
andrewm@0
|
152
|
andrewm@31
|
153
|
andrewm@31
|
154 #ifdef DEBUG_MIDI_INPUT_CONTROLLER
|
andrewm@31
|
155 cout << "Enabling MIDI input port " << portNumber << " (" << device->getName() << ")\n";
|
andrewm@31
|
156 #endif
|
andrewm@31
|
157 device->start();
|
andrewm@31
|
158
|
andrewm@31
|
159 // Save the device in the set of ports
|
andrewm@31
|
160 activePorts_[portNumber] = device;
|
andrewm@31
|
161 }
|
andrewm@31
|
162 else {
|
andrewm@31
|
163 #ifdef DEBUG_MIDI_INPUT_CONTROLLER
|
andrewm@31
|
164 cout << "MIDI input port " << portNumber << " already enabled\n";
|
andrewm@31
|
165 #endif
|
andrewm@0
|
166 }
|
andrewm@0
|
167
|
andrewm@31
|
168 if(isPrimary)
|
andrewm@31
|
169 primaryActivePort_ = portNumber;
|
andrewm@31
|
170
|
andrewm@0
|
171 return true;
|
andrewm@0
|
172 }
|
andrewm@0
|
173
|
andrewm@0
|
174 // Enable all current MIDI ports
|
andrewm@0
|
175
|
andrewm@31
|
176 bool MidiInputController::enableAllPorts(int primaryPortNumber) {
|
andrewm@0
|
177 bool enabledPort = false;
|
andrewm@0
|
178 vector<pair<int, string> > ports = availableMidiDevices();
|
andrewm@0
|
179 vector<pair<int, string> >::iterator it = ports.begin();
|
andrewm@0
|
180
|
andrewm@31
|
181 #ifdef DEBUG_MIDI_INPUT_CONTROLLER
|
andrewm@31
|
182 cout << "Enabling all MIDI input ports\n";
|
andrewm@31
|
183 #endif
|
andrewm@31
|
184
|
andrewm@0
|
185 while(it != ports.end()) {
|
andrewm@0
|
186 // Don't enable MIDI input from our own virtual output
|
andrewm@0
|
187 if(it->second != string(kMidiVirtualOutputName.toUTF8()))
|
andrewm@31
|
188 enabledPort |= enablePort((it++)->first, it->first == primaryPortNumber);
|
andrewm@0
|
189 else
|
andrewm@0
|
190 it++;
|
andrewm@0
|
191 }
|
andrewm@0
|
192
|
andrewm@0
|
193 return enabledPort;
|
andrewm@0
|
194 }
|
andrewm@0
|
195
|
andrewm@0
|
196 // Remove a specific MIDI input source and free associated memory
|
andrewm@0
|
197
|
andrewm@0
|
198 void MidiInputController::disablePort(int portNumber) {
|
andrewm@0
|
199 if(activePorts_.count(portNumber) <= 0)
|
andrewm@0
|
200 return;
|
andrewm@0
|
201
|
andrewm@0
|
202 MidiInput *device = activePorts_[portNumber];
|
andrewm@0
|
203
|
andrewm@0
|
204 if(device == 0)
|
andrewm@0
|
205 return;
|
andrewm@0
|
206
|
andrewm@31
|
207 #ifdef DEBUG_MIDI_INPUT_CONTROLLER
|
andrewm@31
|
208 cout << "Disabling MIDI input port " << portNumber << " (" << device->getName() << ")\n";
|
andrewm@31
|
209 #endif
|
andrewm@31
|
210
|
andrewm@0
|
211 device->stop();
|
andrewm@0
|
212 delete device;
|
andrewm@0
|
213
|
andrewm@0
|
214 activePorts_.erase(portNumber);
|
andrewm@31
|
215 if(primaryActivePort_ == portNumber)
|
andrewm@31
|
216 primaryActivePort_ = -1;
|
andrewm@31
|
217 }
|
andrewm@31
|
218
|
andrewm@31
|
219 // Remove the primary MIDI input source
|
andrewm@31
|
220
|
andrewm@31
|
221 void MidiInputController::disablePrimaryPort() {
|
andrewm@31
|
222 if(primaryActivePort_ < 0)
|
andrewm@31
|
223 return;
|
andrewm@31
|
224 disablePort(primaryActivePort_);
|
andrewm@0
|
225 }
|
andrewm@0
|
226
|
andrewm@0
|
227 // Remove all MIDI input sources and free associated memory
|
andrewm@0
|
228
|
andrewm@31
|
229 void MidiInputController::disableAllPorts(bool auxiliaryOnly) {
|
andrewm@0
|
230 map<int, MidiInput*>::iterator it;
|
andrewm@31
|
231 MidiInput* primaryPort = 0;
|
andrewm@0
|
232
|
andrewm@31
|
233 #ifdef DEBUG_MIDI_INPUT_CONTROLLER
|
andrewm@31
|
234 cout << "Disabling all MIDI input ports\n";
|
andrewm@31
|
235 #endif
|
andrewm@31
|
236
|
andrewm@0
|
237 it = activePorts_.begin();
|
andrewm@0
|
238
|
andrewm@0
|
239 while(it != activePorts_.end()) {
|
andrewm@0
|
240 if(it->second == 0) {
|
andrewm@0
|
241 it++;
|
andrewm@0
|
242 continue;
|
andrewm@0
|
243 }
|
andrewm@31
|
244
|
andrewm@31
|
245 // Save primary port?
|
andrewm@31
|
246 if(it->first == primaryActivePort_ && auxiliaryOnly)
|
andrewm@31
|
247 primaryPort = it->second;
|
andrewm@31
|
248 else {
|
andrewm@31
|
249 it->second->stop(); // disable port
|
andrewm@31
|
250 delete it->second; // free MidiInputCallback
|
andrewm@31
|
251 }
|
andrewm@0
|
252 it++;
|
andrewm@0
|
253 }
|
andrewm@0
|
254
|
andrewm@31
|
255 // Clear all ports including primary
|
andrewm@31
|
256 activePorts_.clear();
|
andrewm@31
|
257
|
andrewm@31
|
258 // But did we save the priamry port?
|
andrewm@31
|
259 if(auxiliaryOnly && primaryPort != 0) {
|
andrewm@31
|
260 // Re-insert primary only
|
andrewm@31
|
261 activePorts_[primaryActivePort_] = primaryPort;
|
andrewm@31
|
262 }
|
andrewm@31
|
263 else
|
andrewm@31
|
264 primaryActivePort_ = -1;
|
andrewm@0
|
265 }
|
andrewm@0
|
266
|
andrewm@31
|
267 // Return the primary active port corresponding to the TK keyboard
|
andrewm@0
|
268
|
andrewm@31
|
269 int MidiInputController::primaryActivePort() {
|
andrewm@31
|
270 return primaryActivePort_;
|
andrewm@31
|
271 }
|
andrewm@31
|
272
|
andrewm@31
|
273 // Return a list of active ports other than the primary
|
andrewm@31
|
274
|
andrewm@31
|
275 vector<int> MidiInputController::auxiliaryActivePorts() {
|
andrewm@0
|
276 vector<int> ports;
|
andrewm@0
|
277
|
andrewm@0
|
278 map<int, MidiInput*>::iterator it;
|
andrewm@0
|
279
|
andrewm@0
|
280 for(it = activePorts_.begin(); it != activePorts_.end(); ++it) {
|
andrewm@31
|
281 if(it->first == primaryActivePort_)
|
andrewm@31
|
282 continue;
|
andrewm@0
|
283 ports.push_back(it->first);
|
andrewm@0
|
284 }
|
andrewm@0
|
285
|
andrewm@0
|
286 return ports;
|
andrewm@0
|
287 }
|
andrewm@0
|
288
|
andrewm@41
|
289 // Get the name of a particular MIDI input port
|
andrewm@41
|
290 String MidiInputController::deviceName(int portNumber) {
|
andrewm@41
|
291 StringArray const& deviceStrings = MidiInput::getDevices();
|
andrewm@41
|
292 if(portNumber < 0 || portNumber >= deviceStrings.size())
|
andrewm@41
|
293 return "";
|
andrewm@41
|
294 return deviceStrings[portNumber];
|
andrewm@41
|
295 }
|
andrewm@41
|
296
|
andrewm@41
|
297 // Find the index of a device with a given name; return -1 if not found
|
andrewm@41
|
298 int MidiInputController::indexOfDeviceNamed(String const& name) {
|
andrewm@41
|
299 StringArray const& deviceStrings = MidiInput::getDevices();
|
andrewm@41
|
300
|
andrewm@41
|
301 for(int i = 0; i < deviceStrings.size(); i++) {
|
andrewm@41
|
302 if(name == deviceStrings[i])
|
andrewm@41
|
303 return i;
|
andrewm@41
|
304 }
|
andrewm@41
|
305
|
andrewm@41
|
306 return -1;
|
andrewm@41
|
307 }
|
andrewm@41
|
308
|
andrewm@0
|
309 // Add a new keyboard segment. Returns a pointer to the newly created segment
|
andrewm@0
|
310 MidiKeyboardSegment* MidiInputController::addSegment(int outputPortNumber,
|
andrewm@0
|
311 int noteMin, int noteMax,
|
andrewm@0
|
312 int channelMask) {
|
andrewm@0
|
313 ScopedLock sl(segmentsMutex_);
|
andrewm@0
|
314
|
andrewm@0
|
315 // Create a new segment and populate its values
|
andrewm@0
|
316 MidiKeyboardSegment *segment = new MidiKeyboardSegment(keyboard_);
|
andrewm@0
|
317
|
andrewm@0
|
318 segment->setMidiOutputController(midiOutputController_);
|
andrewm@0
|
319 segment->setOutputPort(outputPortNumber);
|
andrewm@0
|
320 segment->setNoteRange(noteMin, noteMax);
|
andrewm@0
|
321 segment->setChannelMask(channelMask);
|
andrewm@0
|
322
|
andrewm@0
|
323 // Add the segment to the vector and return the pointer
|
andrewm@0
|
324 segments_.push_back(segment);
|
andrewm@0
|
325 segmentUniqueIdentifier_++;
|
andrewm@0
|
326 return segment;
|
andrewm@0
|
327 }
|
andrewm@0
|
328
|
andrewm@49
|
329 // Remove a segment by index or by object. Returns true if segment existed
|
andrewm@49
|
330 bool MidiInputController::removeSegment(int index) {
|
andrewm@0
|
331 ScopedLock sl(segmentsMutex_);
|
andrewm@0
|
332
|
andrewm@0
|
333 if(index < 0 || index >= segments_.size())
|
andrewm@49
|
334 return false;
|
andrewm@0
|
335
|
andrewm@0
|
336 MidiKeyboardSegment* segment = segments_[index];
|
andrewm@0
|
337 delete segment;
|
andrewm@0
|
338 segments_.erase(segments_.begin() + index);
|
andrewm@0
|
339 segmentUniqueIdentifier_++;
|
andrewm@49
|
340 return true;
|
andrewm@0
|
341 }
|
andrewm@0
|
342
|
andrewm@49
|
343 bool MidiInputController::removeSegment(MidiKeyboardSegment* segment) {
|
andrewm@0
|
344 ScopedLock sl(segmentsMutex_);
|
andrewm@49
|
345 bool found = false;
|
andrewm@0
|
346
|
andrewm@0
|
347 for(int i = 0; i < segments_.size(); i++) {
|
andrewm@0
|
348 if(segments_[i] == segment) {
|
andrewm@0
|
349 delete segment;
|
andrewm@0
|
350 segments_.erase(segments_.begin() + i);
|
andrewm@49
|
351 found = true;
|
andrewm@0
|
352 break;
|
andrewm@0
|
353 }
|
andrewm@0
|
354 }
|
andrewm@0
|
355 segmentUniqueIdentifier_++;
|
andrewm@49
|
356 return found;
|
andrewm@0
|
357 }
|
andrewm@0
|
358
|
andrewm@0
|
359 void MidiInputController::removeAllSegments() {
|
andrewm@0
|
360 ScopedLock sl(segmentsMutex_);
|
andrewm@0
|
361
|
andrewm@0
|
362 for(int i = 0; i < segments_.size(); i++)
|
andrewm@0
|
363 delete segments_[i];
|
andrewm@0
|
364 segments_.clear();
|
andrewm@0
|
365 segmentUniqueIdentifier_++;
|
andrewm@0
|
366 }
|
andrewm@0
|
367
|
andrewm@0
|
368 // Disable any currently active notes
|
andrewm@0
|
369
|
andrewm@0
|
370 void MidiInputController::allNotesOff() {
|
andrewm@0
|
371 ScopedLock sl(segmentsMutex_);
|
andrewm@0
|
372
|
andrewm@0
|
373 for(int i = 0; i < segments_.size(); i++)
|
andrewm@0
|
374 segments_[i]->allNotesOff();
|
andrewm@0
|
375 }
|
andrewm@0
|
376
|
andrewm@33
|
377 // Return the current preset as an XmlElement, suitable for
|
andrewm@33
|
378 // saving to file. This element will need to be deleted when finished
|
andrewm@33
|
379
|
andrewm@33
|
380 XmlElement* MidiInputController::getSegmentPreset() {
|
andrewm@33
|
381 ScopedLock sl(segmentsMutex_);
|
andrewm@33
|
382 XmlElement* controllerElement = new XmlElement("KeyboardSegments");
|
andrewm@33
|
383
|
andrewm@33
|
384 // Add settings for each zone to the element
|
andrewm@33
|
385 for(int i = 0; i < segments_.size(); i++) {
|
andrewm@33
|
386 XmlElement* segmentElement = segments_[i]->getPreset();
|
andrewm@33
|
387 controllerElement->addChildElement(segmentElement);
|
andrewm@33
|
388 }
|
andrewm@33
|
389
|
andrewm@33
|
390 // Return the element
|
andrewm@33
|
391 return controllerElement;
|
andrewm@33
|
392 }
|
andrewm@33
|
393
|
andrewm@33
|
394 // Load keyboard segments from a preset; returns true on success
|
andrewm@33
|
395
|
andrewm@33
|
396 bool MidiInputController::loadSegmentPreset(XmlElement const* preset) {
|
andrewm@33
|
397 ScopedLock sl(segmentsMutex_);
|
andrewm@33
|
398
|
andrewm@33
|
399 for(int i = 0; i < segments_.size(); i++)
|
andrewm@33
|
400 delete segments_[i];
|
andrewm@33
|
401 segments_.clear();
|
andrewm@33
|
402
|
andrewm@33
|
403 XmlElement *element = preset->getChildByName("Segment");
|
andrewm@33
|
404 while(element != 0) {
|
andrewm@33
|
405 // Create a new segment and populate its values
|
andrewm@33
|
406 MidiKeyboardSegment *segment = new MidiKeyboardSegment(keyboard_);
|
andrewm@33
|
407 segment->setMidiOutputController(midiOutputController_);
|
andrewm@33
|
408
|
andrewm@33
|
409 // Load settings for this particular segment
|
andrewm@33
|
410 if(!segment->loadPreset(element)) {
|
andrewm@33
|
411 delete segment;
|
andrewm@33
|
412 for(int i = 0; i < segments_.size(); i++)
|
andrewm@33
|
413 delete segments_[i];
|
andrewm@33
|
414 segments_.clear();
|
andrewm@33
|
415 return false;
|
andrewm@33
|
416 }
|
andrewm@33
|
417
|
andrewm@33
|
418 segments_.push_back(segment);
|
andrewm@33
|
419 element = element->getNextElementWithTagName("Segment");
|
andrewm@33
|
420 }
|
andrewm@33
|
421
|
andrewm@33
|
422 segmentUniqueIdentifier_++;
|
andrewm@33
|
423 return true;
|
andrewm@33
|
424 }
|
andrewm@33
|
425
|
andrewm@49
|
426 // OSC handling for keyboard segments
|
andrewm@49
|
427 OscMessage* MidiInputController::oscControlMessageForSegment(int segment, const char *path, const char *types,
|
andrewm@49
|
428 int numValues, lo_arg **values, void *data) {
|
andrewm@49
|
429 ScopedLock sl(segmentsMutex_);
|
andrewm@49
|
430 if(segment < 0 || segment >= segments_.size())
|
andrewm@49
|
431 return 0;
|
andrewm@49
|
432
|
andrewm@49
|
433 return segments_[segment]->oscControlMethod(path, types, numValues, values, data);
|
andrewm@49
|
434 }
|
andrewm@49
|
435
|
andrewm@0
|
436 // This gets called every time MIDI data becomes available on any input controller. source tells
|
andrewm@0
|
437 // us where the message came from, and may be 0 if being called internally.
|
andrewm@0
|
438
|
andrewm@0
|
439 void MidiInputController::handleIncomingMidiMessage(MidiInput* source, const MidiMessage& message)
|
andrewm@0
|
440 //void MidiInputController::rtMidiCallback(double deltaTime, vector<unsigned char> *message, int inputNumber)
|
andrewm@0
|
441 {
|
andrewm@0
|
442 // Juce will give us one MIDI command per callback, which makes processing easier for us.
|
andrewm@0
|
443
|
andrewm@0
|
444 // Ignore sysex messages for now
|
andrewm@0
|
445 if(message.isSysEx())
|
andrewm@0
|
446 return;
|
andrewm@0
|
447
|
andrewm@0
|
448 // Pull out the raw bytes
|
andrewm@0
|
449 int dataSize = message.getRawDataSize();
|
andrewm@0
|
450 if(dataSize <= 0)
|
andrewm@0
|
451 return;
|
andrewm@0
|
452 const unsigned char *messageData = message.getRawData();
|
andrewm@0
|
453
|
andrewm@0
|
454 // if logging is active
|
andrewm@0
|
455 if (loggingActive)
|
andrewm@0
|
456 {
|
andrewm@0
|
457 ////////////////////////////////////////////////////////
|
andrewm@0
|
458 ////////////////////////////////////////////////////////
|
andrewm@0
|
459 //////////////////// BEGIN LOGGING /////////////////////
|
andrewm@0
|
460
|
andrewm@0
|
461 int midi_channel = (int)(messageData[0]);
|
andrewm@0
|
462 int midi_number = dataSize > 1 ? (int)(messageData[1]) : 0;
|
andrewm@0
|
463 int midi_velocity = dataSize > 2 ? (int)(messageData[2]) : 0;
|
andrewm@0
|
464 timestamp_type timestamp = keyboard_.schedulerCurrentTimestamp();
|
andrewm@0
|
465
|
andrewm@0
|
466 midiLog.write ((char*)×tamp, sizeof (timestamp_type));
|
andrewm@0
|
467 midiLog.write ((char*)&midi_channel, sizeof (int));
|
andrewm@0
|
468 midiLog.write ((char*)&midi_number, sizeof (int));
|
andrewm@0
|
469 midiLog.write ((char*)&midi_velocity, sizeof (int));
|
andrewm@0
|
470
|
andrewm@0
|
471 ///////////////////// END LOGGING //////////////////////
|
andrewm@0
|
472 ////////////////////////////////////////////////////////
|
andrewm@0
|
473 ////////////////////////////////////////////////////////
|
andrewm@0
|
474 }
|
andrewm@0
|
475
|
andrewm@0
|
476 #ifdef MIDI_INPUT_CONTROLLER_DEBUG_RAW
|
andrewm@0
|
477 if(source == 0)
|
andrewm@0
|
478 cout << "MIDI Input [internal]: ";
|
andrewm@0
|
479 else
|
andrewm@0
|
480 cout << "MIDI Input [" << source->getName() << "]: ";
|
andrewm@0
|
481 for(int debugPrint = 0; debugPrint < dataSize; debugPrint++)
|
andrewm@0
|
482 printf("%x ", messageData[debugPrint]);
|
andrewm@0
|
483 cout << endl;
|
andrewm@0
|
484 #endif /* MIDI_INPUT_CONTROLLER_DEBUG_RAW */
|
andrewm@0
|
485
|
andrewm@0
|
486 ScopedLock ksl(keyboard_.performanceDataMutex_);
|
andrewm@0
|
487 ScopedLock sl(segmentsMutex_);
|
andrewm@0
|
488 for(int i = 0; i < segments_.size(); i++) {
|
andrewm@0
|
489 if(segments_[i]->respondsToMessage(message))
|
andrewm@0
|
490 segments_[i]->midiHandlerMethod(source, message);
|
andrewm@0
|
491 }
|
andrewm@0
|
492 }
|
andrewm@0
|
493
|
andrewm@0
|
494 // Destructor. Free any existing callbacks
|
andrewm@0
|
495 MidiInputController::~MidiInputController() {
|
andrewm@0
|
496 if(logFileCreated) {
|
andrewm@0
|
497 midiLog.close();
|
andrewm@0
|
498 }
|
andrewm@31
|
499 disableAllPorts(false);
|
andrewm@0
|
500 removeAllSegments();
|
andrewm@0
|
501 }
|