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 Main.cpp: main startup routines, connecting to Juce library
|
andrewm@0
|
21 */
|
andrewm@0
|
22
|
andrewm@0
|
23 #include "../JuceLibraryCode/JuceHeader.h"
|
andrewm@0
|
24 #include "MainApplicationController.h"
|
andrewm@0
|
25
|
andrewm@0
|
26 #ifndef TOUCHKEYS_NO_GUI
|
andrewm@0
|
27 #include "GUI/MainWindow.h"
|
andrewm@0
|
28 #include "GUI/GraphicsDisplayWindow.h"
|
andrewm@0
|
29 #include "Display/OpenGLJuceCanvas.h"
|
andrewm@0
|
30
|
andrewm@0
|
31 //==============================================================================
|
andrewm@0
|
32 class TouchKeysApplication : public JUCEApplication
|
andrewm@0
|
33 {
|
andrewm@0
|
34 public:
|
andrewm@0
|
35 //==============================================================================
|
andrewm@0
|
36 TouchKeysApplication() {}
|
andrewm@0
|
37
|
andrewm@0
|
38 const String getApplicationName() { return ProjectInfo::projectName; }
|
andrewm@0
|
39 const String getApplicationVersion() { return ProjectInfo::versionString; }
|
andrewm@0
|
40 bool moreThanOneInstanceAllowed() { return true; }
|
andrewm@0
|
41
|
andrewm@0
|
42 //==============================================================================
|
andrewm@0
|
43 void initialise (const String& commandLine) {
|
andrewm@0
|
44 // This method is where you should put your application's initialisation code..
|
andrewm@0
|
45
|
andrewm@0
|
46 mainWindow_ = new MainWindow(controller_);
|
andrewm@0
|
47 keyboardDisplayWindow_ = new GraphicsDisplayWindow("TouchKeys Display", controller_);
|
andrewm@0
|
48
|
andrewm@0
|
49 controller_.setKeyboardDisplayWindow(keyboardDisplayWindow_);
|
andrewm@0
|
50 }
|
andrewm@0
|
51
|
andrewm@0
|
52 void shutdown() {
|
andrewm@0
|
53 // Add your application's shutdown code here..
|
andrewm@0
|
54 mainWindow_ = nullptr; // (deletes our window)
|
andrewm@0
|
55
|
andrewm@0
|
56 controller_.setKeyboardDisplayWindow(0); // Delete display window and disconnect from controller
|
andrewm@0
|
57 keyboardDisplayWindow_ = nullptr;
|
andrewm@0
|
58 }
|
andrewm@0
|
59
|
andrewm@0
|
60 //==============================================================================
|
andrewm@0
|
61 void systemRequestedQuit() {
|
andrewm@0
|
62 // This is called when the app is being asked to quit: you can ignore this
|
andrewm@0
|
63 // request and let the app carry on running, or call quit() to allow the app to close.
|
andrewm@0
|
64 quit();
|
andrewm@0
|
65 }
|
andrewm@0
|
66
|
andrewm@0
|
67 void anotherInstanceStarted (const String& commandLine) {
|
andrewm@0
|
68 // When another instance of the app is launched while this one is running,
|
andrewm@0
|
69 // this method is invoked, and the commandLine parameter tells you what
|
andrewm@0
|
70 // the other instance's command-line arguments were.
|
andrewm@0
|
71 }
|
andrewm@0
|
72
|
andrewm@0
|
73 private:
|
andrewm@0
|
74 ScopedPointer<MainWindow> mainWindow_;
|
andrewm@0
|
75 ScopedPointer<GraphicsDisplayWindow> keyboardDisplayWindow_;
|
andrewm@0
|
76 MainApplicationController controller_;
|
andrewm@0
|
77 };
|
andrewm@0
|
78
|
andrewm@0
|
79 //==============================================================================
|
andrewm@0
|
80 // This macro generates the main() routine that launches the app.
|
andrewm@0
|
81 START_JUCE_APPLICATION (TouchKeysApplication)
|
andrewm@0
|
82
|
andrewm@0
|
83 #else // TOUCHKEYS_NO_GUI
|
andrewm@0
|
84
|
andrewm@0
|
85 #include <getopt.h>
|
andrewm@0
|
86 #include <libgen.h>
|
andrewm@0
|
87 #include <signal.h>
|
andrewm@0
|
88 #include <stdlib.h>
|
andrewm@0
|
89 #include <stdio.h>
|
andrewm@0
|
90
|
andrewm@0
|
91 bool programShouldStop_ = false;
|
andrewm@0
|
92
|
andrewm@0
|
93 static struct option long_options[] = {
|
andrewm@0
|
94 {"help", no_argument, NULL, 'h'},
|
andrewm@0
|
95 {"list", no_argument, NULL, 'l'},
|
andrewm@0
|
96 {"touchkeys", required_argument, NULL, 't'},
|
andrewm@0
|
97 {"midi-input", required_argument, NULL, 'i'},
|
andrewm@0
|
98 {"midi-output", required_argument, NULL, 'o'},
|
andrewm@0
|
99 {"virtual-midi-output", no_argument, NULL, 'O'},
|
andrewm@0
|
100 {0,0,0,0}
|
andrewm@0
|
101 };
|
andrewm@0
|
102
|
andrewm@0
|
103 void sigint_handler(int s){
|
andrewm@0
|
104 programShouldStop_ = true;
|
andrewm@0
|
105 }
|
andrewm@0
|
106
|
andrewm@0
|
107 void usage(const char * processName) // Print usage information and exit
|
andrewm@0
|
108 {
|
andrewm@0
|
109 cerr << "Usage: " << processName << " [-h] [-l] [-t touchkeys] [-i MIDI-in] [-o MIDI-out]\n";
|
andrewm@0
|
110 cerr << " -h: Print this menu\n";
|
andrewm@0
|
111 cerr << " -l: List available TouchKeys and MIDI devices\n";
|
andrewm@0
|
112 cerr << " -t: Specify TouchKeys device path\n";
|
andrewm@0
|
113 cerr << " -i: Specify MIDI input device\n";
|
andrewm@0
|
114 cerr << " -o: Specify MIDI output device\n";
|
andrewm@0
|
115 cerr << " -O: Open virtual MIDI output\n";
|
andrewm@0
|
116 }
|
andrewm@0
|
117
|
andrewm@0
|
118 void list_devices(MainApplicationController& controller)
|
andrewm@0
|
119 {
|
andrewm@0
|
120 std::vector<std::string> touchkeysDevices(controller.availableTouchkeyDevices());
|
andrewm@0
|
121 std::vector<std::pair<int, std::string> > midiInputDevices(controller.availableMIDIInputDevices());
|
andrewm@0
|
122 std::vector<std::pair<int, std::string> > midiOutputDevices(controller.availableMIDIOutputDevices());
|
andrewm@0
|
123
|
andrewm@0
|
124 cerr << "TouchKeys devices: \n";
|
andrewm@0
|
125 if(touchkeysDevices.empty())
|
andrewm@0
|
126 cerr << " [none found]\n";
|
andrewm@0
|
127 else {
|
andrewm@0
|
128 for(std::vector<std::string>::iterator it = touchkeysDevices.begin(); it != touchkeysDevices.end(); ++it) {
|
andrewm@0
|
129 cerr << " /dev/" << *it << "\n";
|
andrewm@0
|
130 }
|
andrewm@0
|
131 }
|
andrewm@0
|
132
|
andrewm@0
|
133 cerr << "\nMIDI input devices: \n";
|
andrewm@0
|
134 if(midiInputDevices.empty())
|
andrewm@0
|
135 cerr << " [none found]\n";
|
andrewm@0
|
136 else {
|
andrewm@0
|
137 for(std::vector<std::pair<int, std::string> >::iterator it = midiInputDevices.begin();
|
andrewm@0
|
138 it != midiInputDevices.end();
|
andrewm@0
|
139 ++it) {
|
andrewm@0
|
140 cerr << " " << it->first << ": " << it->second << "\n";
|
andrewm@0
|
141 }
|
andrewm@0
|
142 }
|
andrewm@0
|
143
|
andrewm@0
|
144 cerr << "\nMIDI output devices: \n";
|
andrewm@0
|
145 if(midiOutputDevices.empty())
|
andrewm@0
|
146 cerr << " [none found]\n";
|
andrewm@0
|
147 else {
|
andrewm@0
|
148 for(std::vector<std::pair<int, std::string> >::iterator it = midiOutputDevices.begin();
|
andrewm@0
|
149 it != midiOutputDevices.end();
|
andrewm@0
|
150 ++it) {
|
andrewm@0
|
151 cerr << " " << it->first << ": " << it->second << "\n";
|
andrewm@0
|
152 }
|
andrewm@0
|
153 }
|
andrewm@0
|
154 }
|
andrewm@0
|
155
|
andrewm@0
|
156 int main (int argc, char* argv[])
|
andrewm@0
|
157 {
|
andrewm@0
|
158 MainApplicationController controller;
|
andrewm@0
|
159 int ch, option_index;
|
andrewm@0
|
160 int midiInputNum = 0, midiOutputNum = 0;
|
andrewm@0
|
161 bool useVirtualMidiOutput = false;
|
andrewm@0
|
162 bool shouldStart = true;
|
andrewm@0
|
163 string touchkeysDevicePath;
|
andrewm@0
|
164
|
andrewm@0
|
165 while((ch = getopt_long(argc, argv, "hli:o:t:O", long_options, &option_index)) != -1)
|
andrewm@0
|
166 {
|
andrewm@0
|
167 if(ch == 'l') { // List devices
|
andrewm@0
|
168 list_devices(controller);
|
andrewm@0
|
169 shouldStart = false;
|
andrewm@0
|
170 break;
|
andrewm@0
|
171 }
|
andrewm@0
|
172 else if(ch == 't') { // TouchKeys device
|
andrewm@0
|
173 touchkeysDevicePath = optarg;
|
andrewm@0
|
174 }
|
andrewm@0
|
175 else if(ch == 'i') { // MIDI input device
|
andrewm@0
|
176 midiInputNum = atoi(optarg);
|
andrewm@0
|
177 }
|
andrewm@0
|
178 else if(ch == 'o') { // MIDI output device
|
andrewm@0
|
179 midiOutputNum = atoi(optarg);
|
andrewm@0
|
180 }
|
andrewm@0
|
181 else if(ch == 'O') { // Virtual MIDI output
|
andrewm@0
|
182 useVirtualMidiOutput = true;
|
andrewm@0
|
183 }
|
andrewm@0
|
184 else {
|
andrewm@0
|
185 usage(basename(argv[0]));
|
andrewm@0
|
186 shouldStart = false;
|
andrewm@0
|
187 break;
|
andrewm@0
|
188 }
|
andrewm@0
|
189 }
|
andrewm@0
|
190
|
andrewm@0
|
191 if(shouldStart) {
|
andrewm@0
|
192 // Main initialization: open TouchKeys and MIDI devices
|
andrewm@0
|
193 try {
|
andrewm@0
|
194 // Check whether TouchKeys device was specified. If not, take the first available one.
|
andrewm@0
|
195 /*if(touchkeysDevicePath == "") {
|
andrewm@0
|
196 std::vector<std::string> touchkeysDevices = controller.availableTouchkeyDevices();
|
andrewm@0
|
197
|
andrewm@0
|
198 if(touchkeysDevices.empty()) {
|
andrewm@0
|
199 cout << "No TouchKeys devices found. Check that the TouchKeys are connected.\n";
|
andrewm@0
|
200 throw new exception;
|
andrewm@0
|
201 }
|
andrewm@0
|
202 else {
|
andrewm@0
|
203 touchkeysDevicePath = "/dev/";
|
andrewm@0
|
204 touchkeysDevicePath.append(touchkeysDevices[0]);
|
andrewm@0
|
205 }
|
andrewm@0
|
206 }*/
|
andrewm@0
|
207
|
andrewm@0
|
208 // Open MIDI devices
|
andrewm@0
|
209 //cout << "Opening MIDI input device " << midiInputNum << endl;
|
andrewm@0
|
210 //controller.enableMIDIInputPort(midiInputNum);
|
andrewm@0
|
211
|
andrewm@0
|
212 // TODO: enable multiple keyboard segments
|
andrewm@0
|
213 if(useVirtualMidiOutput) {
|
andrewm@0
|
214 cout << "Opening virtual MIDI output\n";
|
andrewm@0
|
215 controller.enableMIDIOutputVirtualPort(0, "TouchKeys");
|
andrewm@0
|
216 }
|
andrewm@0
|
217 else {
|
andrewm@0
|
218 cout << "Opening MIDI output device " << midiOutputNum << endl;
|
andrewm@0
|
219 controller.enableMIDIOutputPort(0, midiOutputNum);
|
andrewm@0
|
220 }
|
andrewm@0
|
221
|
andrewm@0
|
222 // Start the TouchKeys
|
andrewm@0
|
223 cout << "Starting the TouchKeys on " << touchkeysDevicePath << " ... ";
|
andrewm@0
|
224 if(!controller.touchkeyDeviceStartupSequence(touchkeysDevicePath.c_str())) {
|
andrewm@0
|
225 cout << "failed: " << controller.touchkeyDeviceErrorMessage() << endl;
|
andrewm@0
|
226 throw new exception;
|
andrewm@0
|
227 }
|
andrewm@0
|
228 else
|
andrewm@0
|
229 cout << "succeeded!\n";
|
andrewm@0
|
230
|
andrewm@0
|
231 // Set up interrupt catching so we can stop with Ctrl-C
|
andrewm@0
|
232 /*struct sigaction sigIntHandler;
|
andrewm@0
|
233
|
andrewm@0
|
234 sigIntHandler.sa_handler = sigint_handler;
|
andrewm@0
|
235 sigemptyset(&sigIntHandler.sa_mask);
|
andrewm@0
|
236 sigIntHandler.sa_flags = 0;
|
andrewm@0
|
237 sigaction(SIGINT, &sigIntHandler, NULL);
|
andrewm@0
|
238
|
andrewm@0
|
239 while(!programShouldStop_) {
|
andrewm@0
|
240 Thread::sleep(50);
|
andrewm@0
|
241 }*/
|
andrewm@0
|
242
|
andrewm@0
|
243 Thread::sleep(1000);
|
andrewm@0
|
244
|
andrewm@0
|
245 cout << "Cleaning up...\n";
|
andrewm@0
|
246 }
|
andrewm@0
|
247 catch(...) {
|
andrewm@0
|
248
|
andrewm@0
|
249 }
|
andrewm@0
|
250 }
|
andrewm@0
|
251
|
andrewm@0
|
252 // Clean up any MessageManager instance that JUCE creates
|
andrewm@0
|
253 DeletedAtShutdown::deleteAll();
|
andrewm@0
|
254 MessageManager::deleteInstance();
|
andrewm@0
|
255 return 0;
|
andrewm@0
|
256 }
|
andrewm@0
|
257
|
andrewm@0
|
258 #endif // TOUCHKEYS_NO_GUI
|