annotate Source/Main.cpp @ 56:b4a2d2ae43cf tip

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