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.h: 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 #ifndef MIDI_INPUT_CONTROLLER_H
|
andrewm@0
|
27 #define MIDI_INPUT_CONTROLLER_H
|
andrewm@0
|
28
|
andrewm@0
|
29 #include <iostream>
|
andrewm@0
|
30 #include <vector>
|
andrewm@0
|
31 #include <map>
|
andrewm@0
|
32 #include <set>
|
andrewm@0
|
33 #include "../JuceLibraryCode/JuceHeader.h"
|
andrewm@0
|
34 #include "PianoKeyboard.h"
|
andrewm@0
|
35 #include "Osc.h"
|
andrewm@0
|
36 #include "MidiKeyboardSegment.h"
|
andrewm@0
|
37
|
andrewm@0
|
38 using namespace std;
|
andrewm@0
|
39
|
andrewm@0
|
40 class MidiOutputController;
|
andrewm@0
|
41
|
andrewm@0
|
42 // MIDI standard messages
|
andrewm@0
|
43
|
andrewm@0
|
44 enum {
|
andrewm@0
|
45 kMidiMessageNoteOff = 0x80,
|
andrewm@0
|
46 kMidiMessageNoteOn = 0x90,
|
andrewm@0
|
47 kMidiMessageAftertouchPoly = 0xA0,
|
andrewm@0
|
48 kMidiMessageControlChange = 0xB0,
|
andrewm@0
|
49 kMidiMessageProgramChange = 0xC0,
|
andrewm@0
|
50 kMidiMessageAftertouchChannel = 0xD0,
|
andrewm@0
|
51 kMidiMessagePitchWheel = 0xE0,
|
andrewm@0
|
52 kMidiMessageSysex = 0xF0,
|
andrewm@0
|
53 kMidiMessageSysexEnd = 0xF7,
|
andrewm@0
|
54 kMidiMessageActiveSense = 0xFE,
|
andrewm@0
|
55 kMidiMessageReset = 0xFF
|
andrewm@0
|
56 };
|
andrewm@0
|
57
|
andrewm@0
|
58 enum {
|
andrewm@0
|
59 kMidiControlAllSoundOff = 120,
|
andrewm@0
|
60 kMidiControlAllControllersOff = 121,
|
andrewm@0
|
61 kMidiControlLocalControl = 122,
|
andrewm@0
|
62 kMidiControlAllNotesOff = 123
|
andrewm@0
|
63 };
|
andrewm@0
|
64
|
andrewm@0
|
65 class MidiInputController : public MidiInputCallback {
|
andrewm@0
|
66 public:
|
andrewm@0
|
67 // Constructor
|
andrewm@0
|
68 MidiInputController(PianoKeyboard& keyboard);
|
andrewm@0
|
69
|
andrewm@0
|
70 // Query available devices
|
andrewm@0
|
71 vector<pair<int, string> > availableMidiDevices();
|
andrewm@0
|
72
|
andrewm@0
|
73 // Add/Remove MIDI input ports;
|
andrewm@0
|
74 // Enable methods return true on success (at least one port enabled)
|
andrewm@31
|
75 bool enablePort(int portNumber, bool isPrimary);
|
andrewm@31
|
76 bool enableAllPorts(int primaryPortNumber);
|
andrewm@0
|
77 void disablePort(int portNumber);
|
andrewm@31
|
78 void disablePrimaryPort();
|
andrewm@31
|
79 void disableAllPorts(bool auxiliaryOnly);
|
andrewm@31
|
80 int primaryActivePort();
|
andrewm@31
|
81 vector<int> auxiliaryActivePorts();
|
andrewm@41
|
82
|
andrewm@41
|
83 // Get the name of a particular port index
|
andrewm@41
|
84 String deviceName(int portNumber);
|
andrewm@41
|
85 int indexOfDeviceNamed(String const& name);
|
andrewm@0
|
86
|
andrewm@0
|
87 // Set/query the output controller
|
andrewm@0
|
88 MidiOutputController* midiOutputController() { return midiOutputController_; }
|
andrewm@0
|
89 void setMidiOutputController(MidiOutputController* ct);
|
andrewm@0
|
90
|
andrewm@0
|
91 // All Notes Off: can be sent by MIDI or controlled programmatically
|
andrewm@0
|
92 void allNotesOff();
|
andrewm@0
|
93
|
andrewm@0
|
94 // Return the number of keyboard segments, and a specific segment
|
andrewm@0
|
95 int numSegments() {
|
andrewm@0
|
96 ScopedLock sl(segmentsMutex_);
|
andrewm@0
|
97 return segments_.size();
|
andrewm@0
|
98 }
|
andrewm@0
|
99 MidiKeyboardSegment* segment(int num) {
|
andrewm@0
|
100 ScopedLock sl(segmentsMutex_);
|
andrewm@0
|
101 if(num < 0 || num >= segments_.size())
|
andrewm@0
|
102 return 0;
|
andrewm@0
|
103 return segments_[num];
|
andrewm@0
|
104 }
|
andrewm@0
|
105 // Return a unique signature which tells us when the MIDI segments have changed,
|
andrewm@0
|
106 // allowing any listeners to re-query all the segments.
|
andrewm@0
|
107 int segmentUniqueIdentifier() {
|
andrewm@0
|
108 return segmentUniqueIdentifier_;
|
andrewm@0
|
109 }
|
andrewm@0
|
110
|
andrewm@0
|
111 // Add a new keyboard segment. Returns a pointer to the newly created segment
|
andrewm@0
|
112 MidiKeyboardSegment* addSegment(int outputPortNumber, int noteMin = 0, int noteMax = 127, int channelMask = 0xFFFF);
|
andrewm@0
|
113
|
andrewm@0
|
114 // Remove a segment by index or by object
|
andrewm@49
|
115 bool removeSegment(int index);
|
andrewm@49
|
116 bool removeSegment(MidiKeyboardSegment* segment);
|
andrewm@0
|
117 void removeAllSegments();
|
andrewm@0
|
118
|
andrewm@33
|
119 // Preset save/load for keyboard segments
|
andrewm@33
|
120 XmlElement* getSegmentPreset();
|
andrewm@33
|
121 bool loadSegmentPreset(XmlElement const* preset);
|
andrewm@33
|
122
|
andrewm@49
|
123 // OSC handling for keyboard segments
|
andrewm@49
|
124 OscMessage* oscControlMessageForSegment(int segment, const char *path, const char *types, int numValues, lo_arg **values, void *data);
|
andrewm@49
|
125
|
andrewm@0
|
126 // Juce MIDI callbacks
|
andrewm@0
|
127 void handleIncomingMidiMessage(MidiInput* source, const MidiMessage& message);
|
andrewm@0
|
128 void handlePartialSysexMessage(MidiInput* source,
|
andrewm@0
|
129 const uint8* messageData,
|
andrewm@0
|
130 int numBytesSoFar,
|
andrewm@0
|
131 double timestamp) {}
|
andrewm@0
|
132
|
andrewm@0
|
133 // OSC method: used to get touch callback data from the keyboard
|
andrewm@0
|
134 // bool oscHandlerMethod(const char *path, const char *types, int numValues, lo_arg **values, void *data);
|
andrewm@0
|
135
|
andrewm@0
|
136 // for logging
|
andrewm@0
|
137 void createLogFile(string midiLog_filename, string path);
|
andrewm@0
|
138 void closeLogFile();
|
andrewm@0
|
139 void startLogging();
|
andrewm@0
|
140 void stopLogging();
|
andrewm@0
|
141
|
andrewm@0
|
142 bool logFileCreated;
|
andrewm@0
|
143 bool loggingActive;
|
andrewm@0
|
144
|
andrewm@0
|
145 // Destructor
|
andrewm@0
|
146 ~MidiInputController();
|
andrewm@0
|
147
|
andrewm@0
|
148 private:
|
andrewm@0
|
149 // ***** Member Variables *****
|
andrewm@0
|
150
|
andrewm@0
|
151 PianoKeyboard& keyboard_; // Reference to main keyboard data
|
andrewm@0
|
152 MidiOutputController *midiOutputController_; // Destination for MIDI output
|
andrewm@0
|
153
|
andrewm@0
|
154 map<int, MidiInput*> activePorts_; // Sources of MIDI data
|
andrewm@31
|
155 int primaryActivePort_; // Which source is primary
|
andrewm@0
|
156
|
andrewm@0
|
157 vector<MidiKeyboardSegment*> segments_; // Segments of the keyboard
|
andrewm@0
|
158 CriticalSection segmentsMutex_; // Mutex protecting the segments list
|
andrewm@0
|
159 int segmentUniqueIdentifier_; // Identifier of when segment structure has changed
|
andrewm@0
|
160
|
andrewm@0
|
161 // for logging
|
andrewm@0
|
162 ofstream midiLog;
|
andrewm@0
|
163 };
|
andrewm@0
|
164
|
andrewm@0
|
165 #endif /* MIDI_INPUT_CONTROLLER_H */ |