annotate Source/MainApplicationController.h @ 56:b4a2d2ae43cf tip

merge
author Andrew McPherson <andrewm@eecs.qmul.ac.uk>
date Fri, 23 Nov 2018 15:48:14 +0000
parents 19650b4076ee
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 MainApplicationController.h: contains the overall glue that holds
andrewm@0 21 together the various parts of the TouchKeys code. It works together
andrewm@0 22 with the user interface to let the user configure the hardware and
andrewm@0 23 manage the mappings, but it is kept separate from any particular user
andrewm@0 24 interface configuration.
andrewm@0 25 */
andrewm@0 26
andrewm@0 27 #ifndef __TouchKeys__MainApplicationController__
andrewm@0 28 #define __TouchKeys__MainApplicationController__
andrewm@0 29
andrewm@11 30 #undef TOUCHKEY_ENTROPY_GENERATOR_ENABLE
andrewm@11 31
andrewm@0 32 #include <iostream>
andrewm@0 33 #include <vector>
andrewm@20 34 #include "TouchKeys/Osc.h"
andrewm@0 35 #include "TouchKeys/MidiInputController.h"
andrewm@0 36 #include "TouchKeys/MidiKeyboardSegment.h"
andrewm@0 37 #include "TouchKeys/MidiOutputController.h"
andrewm@0 38 #include "TouchKeys/TouchkeyDevice.h"
andrewm@9 39 #include "TouchKeys/TouchkeyOscEmulator.h"
andrewm@0 40 #include "Mappings/Vibrato/TouchkeyVibratoMappingFactory.h"
andrewm@0 41 #include "Mappings/PitchBend/TouchkeyPitchBendMappingFactory.h"
andrewm@0 42 #include "Mappings/Control/TouchkeyControlMappingFactory.h"
andrewm@0 43 #include "Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingFactory.h"
andrewm@0 44 #include "Mappings/OnsetAngle/TouchkeyOnsetAngleMappingFactory.h"
andrewm@0 45 #include "Mappings/MultiFingerTrigger/TouchkeyMultiFingerTriggerMappingFactory.h"
andrewm@0 46 #include "Mappings/KeyDivision/TouchkeyKeyDivisionMappingFactory.h"
andrewm@0 47 #include "Mappings/MappingFactorySplitter.h"
andrewm@0 48 #include "TouchKeys/LogPlayback.h"
andrewm@20 49 #include "../JuceLibraryCode/JuceHeader.h"
andrewm@0 50
andrewm@11 51 #ifdef TOUCHKEY_ENTROPY_GENERATOR_ENABLE
andrewm@11 52 #include "TouchKeys/TouchkeyEntropyGenerator.h"
andrewm@11 53 #endif
andrewm@11 54
andrewm@17 55 #ifndef TOUCHKEYS_NO_GUI
andrewm@17 56 #include "GUI/GraphicsDisplayWindow.h"
andrewm@46 57 #include "GUI/PreferencesWindow.h"
andrewm@17 58 class KeyboardTesterDisplay;
andrewm@17 59 #endif
andrewm@17 60
andrewm@0 61 const char kDefaultOscTransmitHost[] = "127.0.0.1";
andrewm@0 62 const char kDefaultOscTransmitPort[] = "8000";
andrewm@6 63 const int kDefaultOscReceivePort = 8001;
andrewm@0 64
andrewm@49 65 class MainApplicationOSCController;
andrewm@17 66
andrewm@0 67 class MainApplicationController : public OscHandler {
andrewm@49 68 friend class MainApplicationOSCController;
andrewm@49 69
andrewm@0 70 public:
andrewm@0 71 // *** Constructor ***
andrewm@0 72 MainApplicationController();
andrewm@0 73
andrewm@0 74 // *** Destructor ***
andrewm@0 75 ~MainApplicationController();
andrewm@0 76
andrewm@41 77 // *** Startup actions ***
andrewm@41 78 void initialise();
andrewm@41 79
andrewm@0 80 // *** TouchKeys device methods ***
andrewm@0 81
andrewm@0 82 // Return the path prefix of the TouchKeys device
andrewm@0 83 std::string touchkeyDevicePrefix();
andrewm@0 84
andrewm@0 85 // Return a list of paths to all available touchkey devices
andrewm@0 86 std::vector<std::string> availableTouchkeyDevices();
andrewm@0 87
andrewm@0 88 // Run the main startup sequence: open device, check its presence,
andrewm@0 89 // start data collection, all in one method. Returns true if successful.
andrewm@0 90 // Will set the error message string if not
andrewm@0 91 bool touchkeyDeviceStartupSequence(const char * path);
andrewm@41 92 void touchkeyDeviceClearErrorMessage();
andrewm@41 93
andrewm@41 94 // Check whether a given touchkey device exists
andrewm@41 95 bool touchkeyDeviceExists(const char * path);
andrewm@0 96
andrewm@0 97 // Select a particular touchkey device
andrewm@41 98 bool openTouchkeyDevice(const char * path);
andrewm@41 99
andrewm@11 100 void closeTouchkeyDevice();
andrewm@0 101
andrewm@0 102 // Check for device present
andrewm@0 103 bool touchkeyDeviceCheckForPresence(int waitMilliseconds = 250, int tries = 10);
andrewm@0 104
andrewm@0 105 // Start/stop the TouchKeys data collection
andrewm@41 106 bool startTouchkeyDevice();
andrewm@41 107 void stopTouchkeyDevice();
andrewm@0 108
andrewm@0 109 // Status queries on TouchKeys
andrewm@0 110 // Returns true if device has been opened
andrewm@41 111 bool touchkeyDeviceIsOpen();
andrewm@41 112
andrewm@0 113 // Return true if device is collecting data
andrewm@11 114 bool touchkeyDeviceIsRunning();
andrewm@11 115
andrewm@0 116 // Returns true if an error has occurred
andrewm@41 117 bool touchkeyDeviceErrorOccurred();
andrewm@41 118
andrewm@0 119 // Return the error message if one occurred
andrewm@41 120 std::string touchkeyDeviceErrorMessage();
andrewm@41 121
andrewm@0 122 // How many octaves on the current device
andrewm@41 123 int touchkeyDeviceNumberOfOctaves();
andrewm@41 124
andrewm@0 125 // Return the lowest MIDI note
andrewm@41 126 int touchkeyDeviceLowestMidiNote();
andrewm@41 127
andrewm@0 128 // Set the lowest MIDI note for the TouchKeys
andrewm@41 129 void touchkeyDeviceSetLowestMidiNote(int note);
andrewm@41 130
andrewm@0 131 // Attempt to autodetect the correct TouchKey octave from MIDI data
andrewm@0 132 void touchkeyDeviceAutodetectLowestMidiNote();
andrewm@0 133 void touchkeyDeviceStopAutodetecting();
andrewm@0 134 bool touchkeyDeviceIsAutodetecting();
andrewm@0 135
andrewm@0 136 // *** MIDI device methods ***
andrewm@0 137
andrewm@0 138 // Return a list of IDs and paths to all available MIDI devices
andrewm@0 139 std::vector<std::pair<int, std::string> > availableMIDIInputDevices() {
andrewm@0 140 return midiInputController_.availableMidiDevices();
andrewm@0 141 }
andrewm@0 142
andrewm@0 143 std::vector<std::pair<int, std::string> > availableMIDIOutputDevices() {
andrewm@0 144 return midiOutputController_.availableMidiDevices();
andrewm@0 145 }
andrewm@0 146
andrewm@0 147 // Return the number of keyboard segments
andrewm@0 148 int midiSegmentsCount() {
andrewm@0 149 return midiInputController_.numSegments();
andrewm@0 150 }
andrewm@0 151 // Return the pointer to a specific segment
andrewm@0 152 MidiKeyboardSegment* midiSegment(int index) {
andrewm@0 153 return midiInputController_.segment(index);
andrewm@0 154 }
andrewm@0 155 // Return a unique signature of segment configuration which
andrewm@0 156 // tells any listeners whether an update has happened
andrewm@0 157 int midiSegmentUniqueIdentifier() {
andrewm@0 158 return midiInputController_.segmentUniqueIdentifier();
andrewm@0 159 }
andrewm@0 160 // Add a new segment, returning the result. Segments are
andrewm@0 161 // stored
andrewm@0 162 MidiKeyboardSegment* midiSegmentAdd();
andrewm@0 163 // Remove a segment
andrewm@13 164 void midiSegmentRemove(MidiKeyboardSegment *segment);
andrewm@0 165
andrewm@0 166 // Select MIDI input/output devices
andrewm@41 167 void enableMIDIInputPort(int portNumber, bool isPrimary);
andrewm@41 168 void enableAllMIDIInputPorts(int primaryPortNumber);
andrewm@41 169 void disableMIDIInputPort(int portNumber);
andrewm@41 170 void disablePrimaryMIDIInputPort();
andrewm@41 171 void disableAllMIDIInputPorts(bool auxiliaryOnly);
andrewm@41 172 void enableMIDIOutputPort(int identifier, int deviceNumber);
andrewm@20 173 #ifndef JUCE_WINDOWS
andrewm@41 174 void enableMIDIOutputVirtualPort(int identifier, const char *name);
andrewm@20 175 #endif
andrewm@41 176 void disableMIDIOutputPort(int identifier);
andrewm@41 177 void disableAllMIDIOutputPorts();
andrewm@0 178
andrewm@0 179 // Get selected MIDI input/output devices by ID
andrewm@31 180 int selectedMIDIPrimaryInputPort() {
andrewm@31 181 return midiInputController_.primaryActivePort();
andrewm@31 182 }
andrewm@31 183 std::vector<int> selectedMIDIAuxInputPorts() {
andrewm@31 184 return midiInputController_.auxiliaryActivePorts();
andrewm@0 185 }
andrewm@0 186 int selectedMIDIOutputPort(int identifier) {
andrewm@0 187 return midiOutputController_.enabledPort(identifier);
andrewm@0 188 }
andrewm@0 189
andrewm@0 190 void midiTouchkeysStandaloneModeEnable();
andrewm@0 191 void midiTouchkeysStandaloneModeDisable();
andrewm@0 192 bool midiTouchkeysStandaloneModeIsEnabled() { return touchkeyStandaloneModeEnabled_; }
andrewm@0 193
andrewm@28 194 // *** Update sync methods ***
andrewm@28 195 // The controller maintains a variable that tells when the devices should be updated
andrewm@28 196 // by the control window component. Whenever it changes value, the devices should be rescanned.
andrewm@28 197
andrewm@28 198 int devicesShouldUpdate() { return deviceUpdateCounter_; }
andrewm@28 199 void tellDevicesToUpdate() { deviceUpdateCounter_++; }
andrewm@28 200
andrewm@0 201 // *** OSC device methods ***
andrewm@0 202
andrewm@41 203 bool oscTransmitEnabled();
andrewm@41 204 void oscTransmitSetEnabled(bool enable);
andrewm@41 205 bool oscTransmitRawDataEnabled();
andrewm@41 206 void oscTransmitSetRawDataEnabled(bool enable);
andrewm@41 207 std::vector<lo_address> oscTransmitAddresses();
andrewm@41 208 int oscTransmitAddAddress(const char * host, const char * port, int proto = LO_UDP);
andrewm@41 209 void oscTransmitRemoveAddress(int index);
andrewm@41 210 void oscTransmitClearAddresses();
andrewm@0 211
andrewm@6 212 // OSC Input (receiver) methods
andrewm@6 213 // Enable or disable on the OSC receive, and report is status
andrewm@41 214 bool oscReceiveEnabled();
andrewm@41 215
andrewm@6 216 // Enable method returns true on success (false only if it was
andrewm@6 217 // unable to set the port)
andrewm@41 218 bool oscReceiveSetEnabled(bool enable);
andrewm@6 219
andrewm@6 220 // Whether the OSC server is running (false means couldn't open port)
andrewm@41 221 bool oscReceiveRunning();
andrewm@41 222
andrewm@6 223 // Get the current OSC receive port
andrewm@41 224 int oscReceivePort();
andrewm@41 225
andrewm@6 226 // Set the current OSC receive port (returns true on success)
andrewm@41 227 bool oscReceiveSetPort(int port);
andrewm@6 228
andrewm@0 229 // *** Display methods ***
andrewm@0 230
andrewm@0 231 KeyboardDisplay& keyboardDisplay() { return keyboardDisplay_; }
andrewm@0 232 #ifndef TOUCHKEYS_NO_GUI
andrewm@0 233 void setKeyboardDisplayWindow(DocumentWindow *window) { keyboardDisplayWindow_ = window; }
andrewm@0 234 void showKeyboardDisplayWindow() {
andrewm@0 235 if(keyboardDisplayWindow_ != 0) {
andrewm@46 236 keyboardDisplayWindow_->addToDesktop(keyboardDisplayWindow_->getDesktopWindowStyleFlags()
andrewm@46 237 | ComponentPeer::windowHasCloseButton);
andrewm@0 238 keyboardDisplayWindow_->setVisible(true);
andrewm@0 239 keyboardDisplayWindow_->toFront(true);
andrewm@0 240 }
andrewm@0 241 }
andrewm@41 242 void setPreferencesWindow(PreferencesWindow *window) { preferencesWindow_ = window; }
andrewm@41 243 void showPreferencesWindow() {
andrewm@41 244 if(preferencesWindow_ != 0) {
andrewm@46 245 preferencesWindow_->addToDesktop(preferencesWindow_->getDesktopWindowStyleFlags()
andrewm@46 246 | ComponentPeer::windowHasCloseButton);
andrewm@41 247 preferencesWindow_->setVisible(true);
andrewm@41 248 preferencesWindow_->toFront(true);
andrewm@41 249 }
andrewm@41 250 }
andrewm@0 251 #endif
andrewm@0 252
andrewm@0 253 // *** Logging methods ***
andrewm@0 254 // Logging methods which record TouchKeys and MIDI data to files for
andrewm@0 255 // later analysis/playback
andrewm@0 256
andrewm@0 257 void startLogging();
andrewm@0 258 void stopLogging();
andrewm@0 259 bool isLogging() { return loggingActive_; }
andrewm@0 260 void setLoggingDirectory(const char *directory);
andrewm@0 261
andrewm@53 262 // Playback methods for log files
andrewm@53 263
andrewm@53 264 void playLogWithDialog();
andrewm@53 265 void stopPlayingLog();
andrewm@53 266 bool isPlayingLog() { return isPlayingLog_; }
andrewm@53 267
andrewm@0 268 // *** OSC handler method (different from OSC device selection) ***
andrewm@0 269
andrewm@0 270 bool oscHandlerMethod(const char *path, const char *types, int numValues, lo_arg **values, void *data);
andrewm@0 271
andrewm@0 272 // *** Mapping methods ***
andrewm@49 273
andrewm@0 274 // Whether experimental (not totally finished/tested) mappings are available
andrewm@0 275 bool experimentalMappingsEnabled() { return experimentalMappingsEnabled_; }
andrewm@0 276 void setExperimentalMappingsEnabled(bool enable) { experimentalMappingsEnabled_ = enable; }
andrewm@0 277
andrewm@33 278 // *** Preset Save/Load ***
andrewm@33 279 // These methods save the current settings to file or load settings
andrewm@33 280 // from a file. They return true on success.
andrewm@33 281 bool savePresetToFile(const char *filename);
andrewm@33 282 bool loadPresetFromFile(const char *filename);
andrewm@55 283
andrewm@33 284 #ifndef TOUCHKEYS_NO_GUI
andrewm@33 285 bool savePresetWithDialog();
andrewm@33 286 bool loadPresetWithDialog();
andrewm@33 287 #endif
andrewm@33 288
andrewm@37 289 // Clears the current preset and restores default settings to zones/mappings
andrewm@37 290 void clearPreset();
andrewm@37 291
andrewm@41 292 // *** Preferences ***
andrewm@41 293
andrewm@41 294 // Whether to automatically start the TouchKeys on startup
andrewm@41 295 bool getPrefsAutoStartTouchKeys();
andrewm@41 296 void setPrefsAutoStartTouchKeys(bool autoStart);
andrewm@41 297
andrewm@41 298 // Whether to automatically detect the TouchKeys octave when they start
andrewm@41 299 bool getPrefsAutodetectOctave();
andrewm@41 300 void setPrefsAutodetectOctave(bool autoDetect);
andrewm@41 301
andrewm@41 302 // Which preset (if any) to load at startup
andrewm@41 303 void setPrefsStartupPresetNone();
andrewm@41 304 bool getPrefsStartupPresetNone();
andrewm@41 305
andrewm@41 306 void setPrefsStartupPresetLastSaved();
andrewm@41 307 bool getPrefsStartupPresetLastSaved();
andrewm@41 308
andrewm@41 309 void setPrefsStartupPresetVibratoPitchBend();
andrewm@41 310 bool getPrefsStartupPresetVibratoPitchBend();
andrewm@41 311
andrewm@41 312 void setPrefsStartupPreset(String const& path);
andrewm@41 313 String getPrefsStartupPreset();
andrewm@41 314
andrewm@41 315 // Reset all preferences
andrewm@41 316 void resetPreferences();
andrewm@41 317
andrewm@41 318 // Load global preferences from file
andrewm@41 319 void loadApplicationPreferences();
andrewm@41 320
andrewm@41 321 // Load a MIDI output device from preexisting application preferences
andrewm@41 322 void loadMIDIOutputFromApplicationPreferences(int zone);
andrewm@41 323
andrewm@17 324 #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST
andrewm@17 325 // *** TouchKeys sensor testing methods ***
andrewm@17 326 // Start testing the TouchKeys sensors
andrewm@17 327 bool touchkeySensorTestStart(const char *path, int firstKey);
andrewm@17 328
andrewm@17 329 // Stop testing the TouchKeys sensors
andrewm@17 330 void touchkeySensorTestStop();
andrewm@17 331
andrewm@17 332 // Is the sensor test running?
andrewm@17 333 bool touchkeySensorTestIsRunning();
andrewm@17 334
andrewm@17 335 // Set the current key that is begin tested
andrewm@17 336 void touchkeySensorTestSetKey(int key);
andrewm@17 337
andrewm@17 338 // Reset the testing state to all sensors off
andrewm@17 339 void touchkeySensorTestResetState();
andrewm@17 340 #endif
andrewm@17 341
andrewm@53 342 #ifdef ENABLE_TOUCHKEYS_FIRMWARE_UPDATE
andrewm@53 343 // Put TouchKeys controller board into bootloader mode
andrewm@53 344 bool touchkeyJumpToBootloader(const char *path);
andrewm@53 345 #endif
andrewm@53 346
andrewm@0 347 // *** Static utility methods ***
andrewm@0 348 static std::string midiNoteName(int noteNumber);
andrewm@0 349 static int midiNoteNumberForName(std::string const& name);
andrewm@0 350
andrewm@0 351 private:
andrewm@33 352 bool savePresetHelper(File& outputFile);
andrewm@33 353 bool loadPresetHelper(File const& inputFile);
andrewm@33 354
andrewm@41 355 // Application properties: for managing preferences
andrewm@41 356 ApplicationProperties applicationProperties_;
andrewm@41 357
andrewm@0 358 // TouchKeys objects
andrewm@49 359 MainApplicationOSCController *mainOscController_;
andrewm@0 360 PianoKeyboard keyboardController_;
andrewm@0 361 MidiInputController midiInputController_;
andrewm@0 362 MidiOutputController midiOutputController_;
andrewm@0 363 OscTransmitter oscTransmitter_;
andrewm@6 364 OscReceiver oscReceiver_;
andrewm@9 365 TouchkeyDevice touchkeyController_;
andrewm@9 366 TouchkeyOscEmulator touchkeyEmulator_;
andrewm@53 367 LogPlayback *logPlayback_;
andrewm@11 368 #ifdef TOUCHKEY_ENTROPY_GENERATOR_ENABLE
andrewm@11 369 TouchkeyEntropyGenerator touchkeyEntropyGenerator_;
andrewm@11 370 bool entropyGeneratorSelected_;
andrewm@11 371 #endif
andrewm@0 372
andrewm@0 373 bool touchkeyErrorOccurred_;
andrewm@0 374 std::string touchkeyErrorMessage_;
andrewm@0 375 bool touchkeyAutodetecting_;
andrewm@0 376 bool touchkeyStandaloneModeEnabled_;
andrewm@28 377 int deviceUpdateCounter_; // Unique number that increments every time devices should
andrewm@28 378 // be rescanned
andrewm@6 379
andrewm@6 380 // OSC information
andrewm@6 381 bool oscReceiveEnabled_;
andrewm@6 382 int oscReceivePort_;
andrewm@6 383
andrewm@0 384 // Mapping objects
andrewm@0 385 bool experimentalMappingsEnabled_;
andrewm@0 386
andrewm@0 387 // Display objects
andrewm@0 388 KeyboardDisplay keyboardDisplay_;
andrewm@0 389 #ifndef TOUCHKEYS_NO_GUI
andrewm@0 390 DocumentWindow *keyboardDisplayWindow_;
andrewm@17 391 KeyboardTesterDisplay *keyboardTesterDisplay_;
andrewm@17 392 GraphicsDisplayWindow *keyboardTesterWindow_;
andrewm@41 393 PreferencesWindow *preferencesWindow_;
andrewm@0 394 #endif
andrewm@0 395
andrewm@0 396 // Segment info
andrewm@0 397 int segmentCounter_;
andrewm@0 398
andrewm@0 399 // Logging info
andrewm@53 400 bool loggingActive_, isPlayingLog_;
andrewm@0 401 std::string loggingDirectory_;
andrewm@0 402 };
andrewm@0 403
andrewm@49 404
andrewm@49 405 // Separate class for handling external OSC control messages since
andrewm@49 406 // one class cannot have two receivers. This one is for all external
andrewm@49 407 // OSC messages which OscHandler on MainApplicationController is for
andrewm@49 408 // internally-generated messages via the PianoKeyboard class.
andrewm@49 409
andrewm@49 410 class MainApplicationOSCController : public OscHandler {
andrewm@49 411 public:
andrewm@49 412 MainApplicationOSCController(MainApplicationController& controller,
andrewm@49 413 OscMessageSource& source) :
andrewm@49 414 controller_(controller), source_(source) {
andrewm@49 415 setOscController(&source_);
andrewm@49 416 addOscListener("/control*");
andrewm@49 417 }
andrewm@49 418
andrewm@49 419 // *** OSC handler method (different from OSC device selection) ***
andrewm@49 420
andrewm@49 421 bool oscHandlerMethod(const char *path, const char *types, int numValues, lo_arg **values, void *data);
andrewm@49 422
andrewm@49 423 private:
andrewm@49 424 // Reply to OSC messages with a status
andrewm@49 425 void oscControlTransmitResult(int result);
andrewm@49 426
andrewm@49 427 MainApplicationController& controller_;
andrewm@49 428 OscMessageSource& source_;
andrewm@49 429 };
andrewm@49 430
andrewm@0 431 #endif /* defined(__TouchKeys__MainApplicationController__) */