Mercurial > hg > touchkeys
view 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 |
line wrap: on
line source
/* TouchKeys: multi-touch musical keyboard control software Copyright (c) 2013 Andrew McPherson This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. ===================================================================== MainApplicationController.h: contains the overall glue that holds together the various parts of the TouchKeys code. It works together with the user interface to let the user configure the hardware and manage the mappings, but it is kept separate from any particular user interface configuration. */ #ifndef __TouchKeys__MainApplicationController__ #define __TouchKeys__MainApplicationController__ #undef TOUCHKEY_ENTROPY_GENERATOR_ENABLE #include <iostream> #include <vector> #include "TouchKeys/Osc.h" #include "TouchKeys/MidiInputController.h" #include "TouchKeys/MidiKeyboardSegment.h" #include "TouchKeys/MidiOutputController.h" #include "TouchKeys/TouchkeyDevice.h" #include "TouchKeys/TouchkeyOscEmulator.h" #include "Mappings/Vibrato/TouchkeyVibratoMappingFactory.h" #include "Mappings/PitchBend/TouchkeyPitchBendMappingFactory.h" #include "Mappings/Control/TouchkeyControlMappingFactory.h" #include "Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingFactory.h" #include "Mappings/OnsetAngle/TouchkeyOnsetAngleMappingFactory.h" #include "Mappings/MultiFingerTrigger/TouchkeyMultiFingerTriggerMappingFactory.h" #include "Mappings/KeyDivision/TouchkeyKeyDivisionMappingFactory.h" #include "Mappings/MappingFactorySplitter.h" #include "TouchKeys/LogPlayback.h" #include "../JuceLibraryCode/JuceHeader.h" #ifdef TOUCHKEY_ENTROPY_GENERATOR_ENABLE #include "TouchKeys/TouchkeyEntropyGenerator.h" #endif #ifndef TOUCHKEYS_NO_GUI #include "GUI/GraphicsDisplayWindow.h" #include "GUI/PreferencesWindow.h" class KeyboardTesterDisplay; #endif const char kDefaultOscTransmitHost[] = "127.0.0.1"; const char kDefaultOscTransmitPort[] = "8000"; const int kDefaultOscReceivePort = 8001; class MainApplicationOSCController; class MainApplicationController : public OscHandler { friend class MainApplicationOSCController; public: // *** Constructor *** MainApplicationController(); // *** Destructor *** ~MainApplicationController(); // *** Startup actions *** void initialise(); // *** TouchKeys device methods *** // Return the path prefix of the TouchKeys device std::string touchkeyDevicePrefix(); // Return a list of paths to all available touchkey devices std::vector<std::string> availableTouchkeyDevices(); // Run the main startup sequence: open device, check its presence, // start data collection, all in one method. Returns true if successful. // Will set the error message string if not bool touchkeyDeviceStartupSequence(const char * path); void touchkeyDeviceClearErrorMessage(); // Check whether a given touchkey device exists bool touchkeyDeviceExists(const char * path); // Select a particular touchkey device bool openTouchkeyDevice(const char * path); void closeTouchkeyDevice(); // Check for device present bool touchkeyDeviceCheckForPresence(int waitMilliseconds = 250, int tries = 10); // Start/stop the TouchKeys data collection bool startTouchkeyDevice(); void stopTouchkeyDevice(); // Status queries on TouchKeys // Returns true if device has been opened bool touchkeyDeviceIsOpen(); // Return true if device is collecting data bool touchkeyDeviceIsRunning(); // Returns true if an error has occurred bool touchkeyDeviceErrorOccurred(); // Return the error message if one occurred std::string touchkeyDeviceErrorMessage(); // How many octaves on the current device int touchkeyDeviceNumberOfOctaves(); // Return the lowest MIDI note int touchkeyDeviceLowestMidiNote(); // Set the lowest MIDI note for the TouchKeys void touchkeyDeviceSetLowestMidiNote(int note); // Attempt to autodetect the correct TouchKey octave from MIDI data void touchkeyDeviceAutodetectLowestMidiNote(); void touchkeyDeviceStopAutodetecting(); bool touchkeyDeviceIsAutodetecting(); // *** MIDI device methods *** // Return a list of IDs and paths to all available MIDI devices std::vector<std::pair<int, std::string> > availableMIDIInputDevices() { return midiInputController_.availableMidiDevices(); } std::vector<std::pair<int, std::string> > availableMIDIOutputDevices() { return midiOutputController_.availableMidiDevices(); } // Return the number of keyboard segments int midiSegmentsCount() { return midiInputController_.numSegments(); } // Return the pointer to a specific segment MidiKeyboardSegment* midiSegment(int index) { return midiInputController_.segment(index); } // Return a unique signature of segment configuration which // tells any listeners whether an update has happened int midiSegmentUniqueIdentifier() { return midiInputController_.segmentUniqueIdentifier(); } // Add a new segment, returning the result. Segments are // stored MidiKeyboardSegment* midiSegmentAdd(); // Remove a segment void midiSegmentRemove(MidiKeyboardSegment *segment); // Select MIDI input/output devices void enableMIDIInputPort(int portNumber, bool isPrimary); void enableAllMIDIInputPorts(int primaryPortNumber); void disableMIDIInputPort(int portNumber); void disablePrimaryMIDIInputPort(); void disableAllMIDIInputPorts(bool auxiliaryOnly); void enableMIDIOutputPort(int identifier, int deviceNumber); #ifndef JUCE_WINDOWS void enableMIDIOutputVirtualPort(int identifier, const char *name); #endif void disableMIDIOutputPort(int identifier); void disableAllMIDIOutputPorts(); // Get selected MIDI input/output devices by ID int selectedMIDIPrimaryInputPort() { return midiInputController_.primaryActivePort(); } std::vector<int> selectedMIDIAuxInputPorts() { return midiInputController_.auxiliaryActivePorts(); } int selectedMIDIOutputPort(int identifier) { return midiOutputController_.enabledPort(identifier); } void midiTouchkeysStandaloneModeEnable(); void midiTouchkeysStandaloneModeDisable(); bool midiTouchkeysStandaloneModeIsEnabled() { return touchkeyStandaloneModeEnabled_; } // *** Update sync methods *** // The controller maintains a variable that tells when the devices should be updated // by the control window component. Whenever it changes value, the devices should be rescanned. int devicesShouldUpdate() { return deviceUpdateCounter_; } void tellDevicesToUpdate() { deviceUpdateCounter_++; } // *** OSC device methods *** bool oscTransmitEnabled(); void oscTransmitSetEnabled(bool enable); bool oscTransmitRawDataEnabled(); void oscTransmitSetRawDataEnabled(bool enable); std::vector<lo_address> oscTransmitAddresses(); int oscTransmitAddAddress(const char * host, const char * port, int proto = LO_UDP); void oscTransmitRemoveAddress(int index); void oscTransmitClearAddresses(); // OSC Input (receiver) methods // Enable or disable on the OSC receive, and report is status bool oscReceiveEnabled(); // Enable method returns true on success (false only if it was // unable to set the port) bool oscReceiveSetEnabled(bool enable); // Whether the OSC server is running (false means couldn't open port) bool oscReceiveRunning(); // Get the current OSC receive port int oscReceivePort(); // Set the current OSC receive port (returns true on success) bool oscReceiveSetPort(int port); // *** Display methods *** KeyboardDisplay& keyboardDisplay() { return keyboardDisplay_; } #ifndef TOUCHKEYS_NO_GUI void setKeyboardDisplayWindow(DocumentWindow *window) { keyboardDisplayWindow_ = window; } void showKeyboardDisplayWindow() { if(keyboardDisplayWindow_ != 0) { keyboardDisplayWindow_->addToDesktop(keyboardDisplayWindow_->getDesktopWindowStyleFlags() | ComponentPeer::windowHasCloseButton); keyboardDisplayWindow_->setVisible(true); keyboardDisplayWindow_->toFront(true); } } void setPreferencesWindow(PreferencesWindow *window) { preferencesWindow_ = window; } void showPreferencesWindow() { if(preferencesWindow_ != 0) { preferencesWindow_->addToDesktop(preferencesWindow_->getDesktopWindowStyleFlags() | ComponentPeer::windowHasCloseButton); preferencesWindow_->setVisible(true); preferencesWindow_->toFront(true); } } #endif // *** Logging methods *** // Logging methods which record TouchKeys and MIDI data to files for // later analysis/playback void startLogging(); void stopLogging(); bool isLogging() { return loggingActive_; } void setLoggingDirectory(const char *directory); // Playback methods for log files void playLogWithDialog(); void stopPlayingLog(); bool isPlayingLog() { return isPlayingLog_; } // *** OSC handler method (different from OSC device selection) *** bool oscHandlerMethod(const char *path, const char *types, int numValues, lo_arg **values, void *data); // *** Mapping methods *** // Whether experimental (not totally finished/tested) mappings are available bool experimentalMappingsEnabled() { return experimentalMappingsEnabled_; } void setExperimentalMappingsEnabled(bool enable) { experimentalMappingsEnabled_ = enable; } // *** Preset Save/Load *** // These methods save the current settings to file or load settings // from a file. They return true on success. bool savePresetToFile(const char *filename); bool loadPresetFromFile(const char *filename); #ifndef TOUCHKEYS_NO_GUI bool savePresetWithDialog(); bool loadPresetWithDialog(); #endif // Clears the current preset and restores default settings to zones/mappings void clearPreset(); // *** Preferences *** // Whether to automatically start the TouchKeys on startup bool getPrefsAutoStartTouchKeys(); void setPrefsAutoStartTouchKeys(bool autoStart); // Whether to automatically detect the TouchKeys octave when they start bool getPrefsAutodetectOctave(); void setPrefsAutodetectOctave(bool autoDetect); // Which preset (if any) to load at startup void setPrefsStartupPresetNone(); bool getPrefsStartupPresetNone(); void setPrefsStartupPresetLastSaved(); bool getPrefsStartupPresetLastSaved(); void setPrefsStartupPresetVibratoPitchBend(); bool getPrefsStartupPresetVibratoPitchBend(); void setPrefsStartupPreset(String const& path); String getPrefsStartupPreset(); // Reset all preferences void resetPreferences(); // Load global preferences from file void loadApplicationPreferences(); // Load a MIDI output device from preexisting application preferences void loadMIDIOutputFromApplicationPreferences(int zone); #ifdef ENABLE_TOUCHKEYS_SENSOR_TEST // *** TouchKeys sensor testing methods *** // Start testing the TouchKeys sensors bool touchkeySensorTestStart(const char *path, int firstKey); // Stop testing the TouchKeys sensors void touchkeySensorTestStop(); // Is the sensor test running? bool touchkeySensorTestIsRunning(); // Set the current key that is begin tested void touchkeySensorTestSetKey(int key); // Reset the testing state to all sensors off void touchkeySensorTestResetState(); #endif #ifdef ENABLE_TOUCHKEYS_FIRMWARE_UPDATE // Put TouchKeys controller board into bootloader mode bool touchkeyJumpToBootloader(const char *path); #endif // *** Static utility methods *** static std::string midiNoteName(int noteNumber); static int midiNoteNumberForName(std::string const& name); private: bool savePresetHelper(File& outputFile); bool loadPresetHelper(File const& inputFile); // Application properties: for managing preferences ApplicationProperties applicationProperties_; // TouchKeys objects MainApplicationOSCController *mainOscController_; PianoKeyboard keyboardController_; MidiInputController midiInputController_; MidiOutputController midiOutputController_; OscTransmitter oscTransmitter_; OscReceiver oscReceiver_; TouchkeyDevice touchkeyController_; TouchkeyOscEmulator touchkeyEmulator_; LogPlayback *logPlayback_; #ifdef TOUCHKEY_ENTROPY_GENERATOR_ENABLE TouchkeyEntropyGenerator touchkeyEntropyGenerator_; bool entropyGeneratorSelected_; #endif bool touchkeyErrorOccurred_; std::string touchkeyErrorMessage_; bool touchkeyAutodetecting_; bool touchkeyStandaloneModeEnabled_; int deviceUpdateCounter_; // Unique number that increments every time devices should // be rescanned // OSC information bool oscReceiveEnabled_; int oscReceivePort_; // Mapping objects bool experimentalMappingsEnabled_; // Display objects KeyboardDisplay keyboardDisplay_; #ifndef TOUCHKEYS_NO_GUI DocumentWindow *keyboardDisplayWindow_; KeyboardTesterDisplay *keyboardTesterDisplay_; GraphicsDisplayWindow *keyboardTesterWindow_; PreferencesWindow *preferencesWindow_; #endif // Segment info int segmentCounter_; // Logging info bool loggingActive_, isPlayingLog_; std::string loggingDirectory_; }; // Separate class for handling external OSC control messages since // one class cannot have two receivers. This one is for all external // OSC messages which OscHandler on MainApplicationController is for // internally-generated messages via the PianoKeyboard class. class MainApplicationOSCController : public OscHandler { public: MainApplicationOSCController(MainApplicationController& controller, OscMessageSource& source) : controller_(controller), source_(source) { setOscController(&source_); addOscListener("/control*"); } // *** OSC handler method (different from OSC device selection) *** bool oscHandlerMethod(const char *path, const char *types, int numValues, lo_arg **values, void *data); private: // Reply to OSC messages with a status void oscControlTransmitResult(int result); MainApplicationController& controller_; OscMessageSource& source_; }; #endif /* defined(__TouchKeys__MainApplicationController__) */