annotate Source/Main.cpp @ 16:61e3c9df4674

Fix bug where TouchKeys standalone mode turns off when mode is changed.
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Mon, 25 Nov 2013 21:36:02 +0000
parents 3580ffe87dc8
children 73d2ec21de9a
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@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