Mercurial > hg > touchkeys
changeset 46:78b9808a2c65
New features in release angle mapping, plus bugfixes on Linux (thanks Martin).
line wrap: on
line diff
--- a/Builds/Linux/Makefile Wed Aug 27 13:18:27 2014 +0100 +++ b/Builds/Linux/Makefile Wed Sep 24 00:29:18 2014 +0100 @@ -18,14 +18,15 @@ TARGET_ARCH := -march=native endif - CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules + CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.1.0" -D "JUCE_APP_VERSION_HEX=0x100" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 CXXFLAGS += $(CFLAGS) LDFLAGS += $(TARGET_ARCH) -L$(BINDIR) -L$(LIBDIR) -L/usr/X11R6/lib/ -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpthread -lrt /usr/local/lib/liblo.a LDDEPS := - RESFLAGS := -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules + RESFLAGS := -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.1.0" -D "JUCE_APP_VERSION_HEX=0x100" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules TARGET := TouchKeys BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH) + CLEANCMD = rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR) endif ifeq ($(CONFIG),Release) @@ -38,14 +39,15 @@ TARGET_ARCH := -march=native endif - CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules + CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.1.0" -D "JUCE_APP_VERSION_HEX=0x100" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -Os CXXFLAGS += $(CFLAGS) LDFLAGS += $(TARGET_ARCH) -L$(BINDIR) -L$(LIBDIR) -fvisibility=hidden -L/usr/X11R6/lib/ -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpthread -lrt /usr/local/lib/liblo.a LDDEPS := - RESFLAGS := -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules + RESFLAGS := -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "JUCE_APP_VERSION=0.1.0" -D "JUCE_APP_VERSION_HEX=0x100" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules TARGET := TouchKeys BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH) + CLEANCMD = rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR) endif OBJECTS := \ @@ -58,6 +60,7 @@ $(OBJDIR)/TouchkeyVibratoMappingShortEditor_27ad15dd.o \ $(OBJDIR)/TouchkeyVibratoMapping_ea5c5156.o \ $(OBJDIR)/TouchkeyVibratoMappingFactory_f90040de.o \ + $(OBJDIR)/TouchkeyReleaseAngleMappingExtendedEditor_cdb58770.o \ $(OBJDIR)/TouchkeyReleaseAngleMapping_170b0b0a.o \ $(OBJDIR)/TouchkeyReleaseAngleMappingFactory_9052f4aa.o \ $(OBJDIR)/TouchkeyPitchBendMappingShortEditor_6afc649d.o \ @@ -129,9 +132,7 @@ clean: @echo Cleaning TouchKeys - -@rm -f $(OUTDIR)/$(TARGET) - -@rm -rf $(OBJDIR)/* - -@rm -rf $(OBJDIR) + @$(CLEANCMD) strip: @echo Stripping TouchKeys @@ -182,6 +183,11 @@ @echo "Compiling TouchkeyVibratoMappingFactory.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/TouchkeyReleaseAngleMappingExtendedEditor_cdb58770.o: ../../Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingExtendedEditor.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling TouchkeyReleaseAngleMappingExtendedEditor.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/TouchkeyReleaseAngleMapping_170b0b0a.o: ../../Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMapping.cpp -@mkdir -p $(OBJDIR) @echo "Compiling TouchkeyReleaseAngleMapping.cpp"
--- a/Builds/Linux32/Makefile Wed Aug 27 13:18:27 2014 +0100 +++ b/Builds/Linux32/Makefile Wed Sep 24 00:29:18 2014 +0100 @@ -18,14 +18,15 @@ TARGET_ARCH := -march=native endif - CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_BCF8FE09=1" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules + CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_BCF8FE09=1" -D "JUCE_APP_VERSION=0.1.0" -D "JUCE_APP_VERSION_HEX=0x100" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 -m32 CXXFLAGS += $(CFLAGS) LDFLAGS += $(TARGET_ARCH) -L$(BINDIR) -L$(LIBDIR) -L/usr/X11R6/lib/ -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpthread -lrt -L/usr/lib/i386-linux-gnu -L/usr/lib/i386-linux-gnu/mesa -m32 /usr/local/lib/liblo32.a LDDEPS := - RESFLAGS := -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_BCF8FE09=1" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules + RESFLAGS := -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCER_LINUX_MAKE_BCF8FE09=1" -D "JUCE_APP_VERSION=0.1.0" -D "JUCE_APP_VERSION_HEX=0x100" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules TARGET := TouchKeys BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH) + CLEANCMD = rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR) endif ifeq ($(CONFIG),Release) @@ -38,14 +39,15 @@ TARGET_ARCH := -march=native endif - CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_BCF8FE09=1" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules + CPPFLAGS := $(DEPFLAGS) -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_BCF8FE09=1" -D "JUCE_APP_VERSION=0.1.0" -D "JUCE_APP_VERSION_HEX=0x100" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -Os -m32 CXXFLAGS += $(CFLAGS) LDFLAGS += $(TARGET_ARCH) -L$(BINDIR) -L$(LIBDIR) -fvisibility=hidden -L/usr/X11R6/lib/ -lGL -lX11 -lXext -lXinerama -lasound -ldl -lfreetype -lpthread -lrt -L/usr/lib/i386-linux-gnu -L/usr/lib/i386-linux-gnu/mesa -m32 /usr/local/lib/liblo32.a LDDEPS := - RESFLAGS := -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_BCF8FE09=1" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules + RESFLAGS := -D "LINUX=1" -D "NDEBUG=1" -D "JUCER_LINUX_MAKE_BCF8FE09=1" -D "JUCE_APP_VERSION=0.1.0" -D "JUCE_APP_VERSION_HEX=0x100" -I /usr/include -I /usr/include/freetype2 -I ../../JuceLibraryCode -I ../../../juce/modules TARGET := TouchKeys BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH) + CLEANCMD = rm -rf $(OUTDIR)/$(TARGET) $(OBJDIR) endif OBJECTS := \ @@ -58,6 +60,7 @@ $(OBJDIR)/TouchkeyVibratoMappingShortEditor_27ad15dd.o \ $(OBJDIR)/TouchkeyVibratoMapping_ea5c5156.o \ $(OBJDIR)/TouchkeyVibratoMappingFactory_f90040de.o \ + $(OBJDIR)/TouchkeyReleaseAngleMappingExtendedEditor_cdb58770.o \ $(OBJDIR)/TouchkeyReleaseAngleMapping_170b0b0a.o \ $(OBJDIR)/TouchkeyReleaseAngleMappingFactory_9052f4aa.o \ $(OBJDIR)/TouchkeyPitchBendMappingShortEditor_6afc649d.o \ @@ -129,9 +132,7 @@ clean: @echo Cleaning TouchKeys - -@rm -f $(OUTDIR)/$(TARGET) - -@rm -rf $(OBJDIR)/* - -@rm -rf $(OBJDIR) + @$(CLEANCMD) strip: @echo Stripping TouchKeys @@ -182,6 +183,11 @@ @echo "Compiling TouchkeyVibratoMappingFactory.cpp" @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" +$(OBJDIR)/TouchkeyReleaseAngleMappingExtendedEditor_cdb58770.o: ../../Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingExtendedEditor.cpp + -@mkdir -p $(OBJDIR) + @echo "Compiling TouchkeyReleaseAngleMappingExtendedEditor.cpp" + @$(CXX) $(CXXFLAGS) -o "$@" -c "$<" + $(OBJDIR)/TouchkeyReleaseAngleMapping_170b0b0a.o: ../../Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMapping.cpp -@mkdir -p $(OBJDIR) @echo "Compiling TouchkeyReleaseAngleMapping.cpp"
--- a/JuceLibraryCode/AppConfig.h Wed Aug 27 13:18:27 2014 +0100 +++ b/JuceLibraryCode/AppConfig.h Wed Sep 24 00:29:18 2014 +0100 @@ -151,5 +151,9 @@ //#define JUCE_WEB_BROWSER #endif +#ifndef JUCE_ENABLE_LIVE_CONSTANT_EDITOR + //#define JUCE_ENABLE_LIVE_CONSTANT_EDITOR +#endif + #endif // __JUCE_APPCONFIG_IJU11L__
--- a/JuceLibraryCode/BinaryData.cpp Wed Aug 27 13:18:27 2014 +0100 +++ b/JuceLibraryCode/BinaryData.cpp Wed Sep 24 00:29:18 2014 +0100 @@ -429,8 +429,6 @@ return 0; } -const int namedResourceListSize = 3; - const char* namedResourceList[] = { "tkicon128_png",
--- a/JuceLibraryCode/BinaryData.h Wed Aug 27 13:18:27 2014 +0100 +++ b/JuceLibraryCode/BinaryData.h Wed Sep 24 00:29:18 2014 +0100 @@ -4,6 +4,9 @@ */ +#ifndef BINARYDATA_H_20480568_INCLUDED +#define BINARYDATA_H_20480568_INCLUDED + namespace BinaryData { extern const char* tkicon128_png; @@ -19,9 +22,11 @@ extern const char* namedResourceList[]; // Number of elements in the namedResourceList array. - extern const int namedResourceListSize; + const int namedResourceListSize = 3; // If you provide the name of one of the binary resource variables above, this function will // return the corresponding data and its size (or a null pointer if the name isn't found). const char* getNamedResource (const char* resourceNameUTF8, int& dataSizeInBytes) throw(); } + +#endif
--- a/JuceLibraryCode/JuceHeader.h Wed Aug 27 13:18:27 2014 +0100 +++ b/JuceLibraryCode/JuceHeader.h Wed Sep 24 00:29:18 2014 +0100 @@ -32,11 +32,13 @@ using namespace juce; #endif +#if ! JUCE_DONT_DECLARE_PROJECTINFO namespace ProjectInfo { const char* const projectName = "TouchKeys"; const char* const versionString = "0.1.0"; const int versionNumber = 0x100; } +#endif #endif // __APPHEADERFILE_IJU11L__
--- a/Source/Display/KeyboardDisplay.cpp Wed Aug 27 13:18:27 2014 +0100 +++ b/Source/Display/KeyboardDisplay.cpp Wed Sep 24 00:29:18 2014 +0100 @@ -159,14 +159,27 @@ // Draw the keys themselves first, with analog values if present, then draw the touches for(int key = lowestMidiNote_; key <= highestMidiNote_; key++) { if(keyShape(key) >= 0) { - // White keys: draw and move the frame over for the next key - drawWhiteKey(0, 0, keyShape(key), key == lowestMidiNote_, key == highestMidiNote_, - /*(key == currentHighlightedKey_) ||*/ midiActiveForKey_[key], keyDivisionsForNote_[key]); - // Analog slider should be centered with respect to the back of the white key - if(analogSensorsPresent_ && keyShape(key) >= 0) { - float sliderOffset = kWhiteKeyBackOffsets[keyShape(key)] + (kWhiteKeyBackWidths[keyShape(key)] - kAnalogSliderWidth) * 0.5; - drawAnalogSlider(sliderOffset, kWhiteKeyFrontLength + kWhiteKeyBackLength + kAnalogSliderVerticalSpacing, - analogValueIsCalibratedForKey_[key], true, analogValueForKey_[key]); + if(key < 0 || key > 127) { + // Safety check + drawWhiteKey(0, 0, keyShape(key), key == lowestMidiNote_, key == highestMidiNote_, + false, 1); + // Analog slider should be centered with respect to the back of the white key + if(analogSensorsPresent_ && keyShape(key) >= 0) { + float sliderOffset = kWhiteKeyBackOffsets[keyShape(key)] + (kWhiteKeyBackWidths[keyShape(key)] - kAnalogSliderWidth) * 0.5; + drawAnalogSlider(sliderOffset, kWhiteKeyFrontLength + kWhiteKeyBackLength + kAnalogSliderVerticalSpacing, + false, true, 0); + } + } + else { + // White keys: draw and move the frame over for the next key + drawWhiteKey(0, 0, keyShape(key), key == lowestMidiNote_, key == highestMidiNote_, + /*(key == currentHighlightedKey_) ||*/ midiActiveForKey_[key], keyDivisionsForNote_[key]); + // Analog slider should be centered with respect to the back of the white key + if(analogSensorsPresent_ && keyShape(key) >= 0) { + float sliderOffset = kWhiteKeyBackOffsets[keyShape(key)] + (kWhiteKeyBackWidths[keyShape(key)] - kAnalogSliderWidth) * 0.5; + drawAnalogSlider(sliderOffset, kWhiteKeyFrontLength + kWhiteKeyBackLength + kAnalogSliderVerticalSpacing, + analogValueIsCalibratedForKey_[key], true, analogValueForKey_[key]); + } } glTranslatef(kWhiteKeyFrontWidth + kInterKeySpacing, 0, 0); } @@ -177,10 +190,21 @@ float offsetV = kWhiteKeyFrontLength + kWhiteKeyBackLength - kBlackKeyLength; glTranslatef(offsetH, offsetV, 0.0); - drawBlackKey(0, 0, /*(key == currentHighlightedKey_) ||*/ midiActiveForKey_[key], keyDivisionsForNote_[key]); - if(analogSensorsPresent_) { - drawAnalogSlider((kBlackKeyWidth - kAnalogSliderWidth) * 0.5, kBlackKeyLength + kAnalogSliderVerticalSpacing, - analogValueIsCalibratedForKey_[key], false, analogValueForKey_[key]); + + if(key < 0 || key > 127) { + // Safety check + drawBlackKey(0, 0, false, 1); + if(analogSensorsPresent_) { + drawAnalogSlider((kBlackKeyWidth - kAnalogSliderWidth) * 0.5, kBlackKeyLength + kAnalogSliderVerticalSpacing, + false, false, 0); + } + } + else { + drawBlackKey(0, 0, /*(key == currentHighlightedKey_) ||*/ midiActiveForKey_[key], keyDivisionsForNote_[key]); + if(analogSensorsPresent_) { + drawAnalogSlider((kBlackKeyWidth - kAnalogSliderWidth) * 0.5, kBlackKeyLength + kAnalogSliderVerticalSpacing, + analogValueIsCalibratedForKey_[key], false, analogValueForKey_[key]); + } } glTranslatef(-offsetH, -offsetV, 0.0); }
--- a/Source/GUI/GraphicsDisplayWindow.h Wed Aug 27 13:18:27 2014 +0100 +++ b/Source/GUI/GraphicsDisplayWindow.h Wed Sep 24 00:29:18 2014 +0100 @@ -37,7 +37,7 @@ { public: GraphicsDisplayWindow(String name, KeyboardDisplay& display) - : DocumentWindow(name, Colours::lightgrey, DocumentWindow::allButtons), + : DocumentWindow(name, Colours::lightgrey, DocumentWindow::allButtons, false), display_(display) { // Initialize an OpenGL graphics object as the content with a default size
--- a/Source/GUI/PreferencesWindow.h Wed Aug 27 13:18:27 2014 +0100 +++ b/Source/GUI/PreferencesWindow.h Wed Sep 24 00:29:18 2014 +0100 @@ -22,7 +22,7 @@ { public: PreferencesWindow(MainApplicationController& controller) - : DocumentWindow("Preferences", Colours::lightgrey, DocumentWindow::allButtons) + : DocumentWindow("Preferences", Colours::lightgrey, DocumentWindow::allButtons, false) { // Make a new preferences component preferencesComponent_ = new PreferencesComponent();
--- a/Source/MainApplicationController.h Wed Aug 27 13:18:27 2014 +0100 +++ b/Source/MainApplicationController.h Wed Sep 24 00:29:18 2014 +0100 @@ -54,7 +54,7 @@ #ifndef TOUCHKEYS_NO_GUI #include "GUI/GraphicsDisplayWindow.h" -#include "GUI/PReferencesWindow.h" +#include "GUI/PreferencesWindow.h" class KeyboardTesterDisplay; #endif @@ -232,6 +232,8 @@ void setKeyboardDisplayWindow(DocumentWindow *window) { keyboardDisplayWindow_ = window; } void showKeyboardDisplayWindow() { if(keyboardDisplayWindow_ != 0) { + keyboardDisplayWindow_->addToDesktop(keyboardDisplayWindow_->getDesktopWindowStyleFlags() + | ComponentPeer::windowHasCloseButton); keyboardDisplayWindow_->setVisible(true); keyboardDisplayWindow_->toFront(true); } @@ -239,6 +241,8 @@ void setPreferencesWindow(PreferencesWindow *window) { preferencesWindow_ = window; } void showPreferencesWindow() { if(preferencesWindow_ != 0) { + preferencesWindow_->addToDesktop(preferencesWindow_->getDesktopWindowStyleFlags() + | ComponentPeer::windowHasCloseButton); preferencesWindow_->setVisible(true); preferencesWindow_->toFront(true); }
--- a/Source/Mappings/KeyDivision/TouchkeyKeyDivisionMapping.cpp Wed Aug 27 13:18:27 2014 +0100 +++ b/Source/Mappings/KeyDivision/TouchkeyKeyDivisionMapping.cpp Wed Sep 24 00:29:18 2014 +0100 @@ -29,7 +29,7 @@ const int TouchkeyKeyDivisionMapping::kDefaultNumberOfSegments = 2; const timestamp_diff_type TouchkeyKeyDivisionMapping::kDefaultDetectionTimeout = milliseconds_to_timestamp(25.0); -const int TouchkeyKeyDivisionMapping::kDefaultDetectionParameter = kDetectionParameterYPosition; +const int TouchkeyKeyDivisionMapping::kDefaultDetectionParameter = kDetectionParameterYPositionAndNumberOfTouches; const int TouchkeyKeyDivisionMapping::kDefaultRetriggerNumFrames = 2; // Main constructor takes references/pointers from objects which keep track @@ -41,7 +41,7 @@ Node<key_position>* positionBuffer, KeyPositionTracker* positionTracker) : TouchkeyBaseMapping(keyboard, factory, noteNumber, touchBuffer, positionBuffer, positionTracker), numberOfSegments_(kDefaultNumberOfSegments), candidateSegment_(-1), detectedSegment_(-1), defaultSegment_(0), -detectionParameter_(kDefaultDetectionParameter), retriggerable_(false), retriggerNumFrames_(kDefaultRetriggerNumFrames), +detectionParameter_(kDefaultDetectionParameter), retriggerable_(true), retriggerNumFrames_(kDefaultRetriggerNumFrames), retriggerKeepsVelocity_(true), midiNoteOnTimestamp_(missing_value<timestamp_type>::missing()), timeout_(kDefaultDetectionTimeout), lastNumActiveTouches_(-1)
--- a/Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMapping.cpp Wed Aug 27 13:18:27 2014 +0100 +++ b/Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMapping.cpp Wed Sep 24 00:29:18 2014 +0100 @@ -23,14 +23,20 @@ */ #include "TouchkeyReleaseAngleMapping.h" +#include "TouchkeyReleaseAngleMappingFactory.h" #include "../MappingFactory.h" #include "../../TouchKeys/MidiOutputController.h" #include "../MappingScheduler.h" +#define DEBUG_RELEASE_ANGLE_MAPPING + // Class constants const int TouchkeyReleaseAngleMapping::kDefaultFilterBufferLength = 30; const timestamp_diff_type TouchkeyReleaseAngleMapping::kDefaultMaxLookbackTime = milliseconds_to_timestamp(100); +const float TouchkeyReleaseAngleMapping::kDefaultUpMinimumAngle = 1.0; +const float TouchkeyReleaseAngleMapping::kDefaultDownMinimumAngle = 1.0; + // Main constructor takes references/pointers from objects which keep track // of touch location, continuous key position and the state detected from that // position. The PianoKeyboard object is strictly required as it gives access to @@ -39,16 +45,13 @@ TouchkeyReleaseAngleMapping::TouchkeyReleaseAngleMapping(PianoKeyboard &keyboard, MappingFactory *factory, int noteNumber, Node<KeyTouchFrame>* touchBuffer, Node<key_position>* positionBuffer, KeyPositionTracker* positionTracker) : TouchkeyBaseMapping(keyboard, factory, noteNumber, touchBuffer, positionBuffer, positionTracker, false), + upEnabled_(true), downEnabled_(true), upMinimumAngle_(kDefaultUpMinimumAngle), downMinimumAngle_(kDefaultDownMinimumAngle), pastSamples_(kDefaultFilterBufferLength), maxLookbackTime_(kDefaultMaxLookbackTime) { + for(int i = 0; i < RELEASE_ANGLE_MAX_SEQUENCE_LENGTH; i++) + upNotes_[i] = downNotes_[i] = upVelocities_[i] = downVelocities_[i] = 0; } -// Copy constructor -/*TouchkeyReleaseAngleMapping::TouchkeyReleaseAngleMapping(TouchkeyReleaseAngleMapping const& obj) -: TouchkeyBaseMapping(obj), pastSamples_(obj.pastSamples_), maxLookbackTime_(obj.maxLookbackTime_) -{ -}*/ - // Reset state back to defaults void TouchkeyReleaseAngleMapping::reset() { ScopedLock sl(sampleBufferMutex_); @@ -62,6 +65,64 @@ // Message is only sent at release; resend may not apply here. } +// Parameters for release angle algorithm +void TouchkeyReleaseAngleMapping::setWindowSize(float windowSize) { + // This was passed in in milliseconds and needs to be converted to a timestamp type + maxLookbackTime_ = milliseconds_to_timestamp(windowSize); +} + +void TouchkeyReleaseAngleMapping::setUpMessagesEnabled(bool enable) { + upEnabled_ = enable; +} + +void TouchkeyReleaseAngleMapping::setDownMessagesEnabled(bool enable) { + downEnabled_ = enable; +} + +void TouchkeyReleaseAngleMapping::setUpMinimumAngle(float minAngle) { + upMinimumAngle_ = fabsf(minAngle); +} + +void TouchkeyReleaseAngleMapping::setUpNote(int sequence, int note) { + if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH) + return; + if(note < 0 || note > 127) + upNotes_[sequence] = 0; + else + upNotes_[sequence] = note; +} + +void TouchkeyReleaseAngleMapping::setUpVelocity(int sequence, int velocity) { + if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH) + return; + if(velocity < 0 || velocity > 127) + upVelocities_[sequence] = 0; + else + upVelocities_[sequence] = velocity; +} + +void TouchkeyReleaseAngleMapping::setDownMinimumAngle(float minAngle) { + downMinimumAngle_ = fabsf(minAngle); +} + +void TouchkeyReleaseAngleMapping::setDownNote(int sequence, int note) { + if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH) + return; + if(note < 0 || note > 127) + downNotes_[sequence] = 0; + else + downNotes_[sequence] = note; +} + +void TouchkeyReleaseAngleMapping::setDownVelocity(int sequence, int velocity) { + if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH) + return; + if(velocity < 0 || velocity > 127) + downVelocities_[sequence] = 0; + else + downVelocities_[sequence] = velocity; +} + // This method receives data from the touch buffer or possibly the continuous key angle (not used here) void TouchkeyReleaseAngleMapping::triggerReceived(TriggerSource* who, timestamp_type timestamp) { if(who == touchBuffer_) { @@ -85,7 +146,11 @@ return nextScheduledTimestamp_; } -void TouchkeyReleaseAngleMapping::processRelease(timestamp_type timestamp) { +void TouchkeyReleaseAngleMapping::midiNoteOffReceived(int channel) { + processRelease(); +} + +void TouchkeyReleaseAngleMapping::processRelease(/*timestamp_type timestamp*/) { if(!noteIsOn_) { return; } @@ -96,15 +161,16 @@ float calculatedVelocity = missing_value<float>::missing(); bool touchWasOn = false; - - //std::cout << "processRelease begin = " << pastSamples_.beginIndex() << " end = " << pastSamples_.endIndex() << "\n"; - if(!pastSamples_.empty()) { Node<KeyTouchFrame>::size_type index = pastSamples_.endIndex() - 1; Node<KeyTouchFrame>::size_type mostRecentTouchPresentIndex = pastSamples_.endIndex() - 1; + timestamp_type lastTimestamp = pastSamples_.timestampAt(index); + while(index >= pastSamples_.beginIndex()) { - //std::cout << "examining sample " << index << " with " << pastSamples_[index].count << " touches and time diff " << timestamp - pastSamples_.timestampAt(index) << "\n"; - if(timestamp - pastSamples_.timestampAt(index) >= maxLookbackTime_) +#ifdef DEBUG_RELEASE_ANGLE_MAPPING + std::cout << "examining sample " << index << " with " << pastSamples_[index].count << " touches and time diff " << lastTimestamp - pastSamples_.timestampAt(index) << "\n"; +#endif + if(lastTimestamp - pastSamples_.timestampAt(index) >= maxLookbackTime_) break; if(pastSamples_[index].count == 0) { if(touchWasOn) { @@ -129,8 +195,6 @@ if(index < pastSamples_.beginIndex()) index = pastSamples_.beginIndex(); - //std::cout << "done\n"; - // Need at least two points for this calculation to work timestamp_type endingTimestamp = pastSamples_.timestampAt(mostRecentTouchPresentIndex); timestamp_type startingTimestamp = pastSamples_.timestampAt(index); @@ -140,32 +204,78 @@ calculatedVelocity = (endingPosition - startingPosition) / (endingTimestamp - startingTimestamp); } else { // DEBUG +#ifdef DEBUG_RELEASE_ANGLE_MAPPING std::cout << "Found 0 timestamp difference on key release (indices " << index << " and " << pastSamples_.endIndex() - 1 << "\n"; +#endif } } - else + else { +#ifdef DEBUG_RELEASE_ANGLE_MAPPING std::cout << "Found empty touch buffer on key release\n"; +#endif + } sampleBufferMutex_.exit(); if(!missing_value<float>::isMissing(calculatedVelocity)) { +#ifdef DEBUG_RELEASE_ANGLE_MAPPING std::cout << "Found release velocity " << calculatedVelocity << " on note " << noteNumber_ << std::endl; +#endif sendReleaseAngleMessage(calculatedVelocity); } - // Check if we're suppose to clean up now + // Check if we're supposed to clean up now finished_ = true; if(finishRequested_) acknowledgeFinish(); // KLUDGE } -#define TROMBONE void TouchkeyReleaseAngleMapping::sendReleaseAngleMessage(float releaseAngle, bool force) { if(force || !suspended_) { keyboard_.sendMessage("/touchkeys/releaseangle", "if", noteNumber_, releaseAngle, LO_ARGS_END); + if(keyboard_.midiOutputController() == 0) + return; + + int port = static_cast<TouchkeyReleaseAngleMappingFactory*>(factory_)->segment().outputPort(); + int ch = keyboard_.key(noteNumber_)->midiChannel(); + + // Check if the release angle exceeds either the up or down threshold + if(releaseAngle > 0 && fabs(releaseAngle) >= upMinimumAngle_ && upEnabled_) { +#ifdef DEBUG_RELEASE_ANGLE_MAPPING + std::cout << "Send up-release messages for note " << noteNumber_ << " on channel " << ch << "\n"; +#endif + // Send key switches: note on and note off in reverse orders + for(int i = 0; i < RELEASE_ANGLE_MAX_SEQUENCE_LENGTH; i++) { + if(upNotes_[i] != 0) + keyboard_.midiOutputController()->sendNoteOn(port, ch, upNotes_[i], upVelocities_[i]); + } + + for(int i = RELEASE_ANGLE_MAX_SEQUENCE_LENGTH - 1; i >= 0; i--) { + if(upNotes_[i] != 0) + keyboard_.midiOutputController()->sendNoteOff(port, ch, upNotes_[i]); + } + } + else if(releaseAngle < 0 && fabs(releaseAngle) >= downMinimumAngle_ && downEnabled_) { +#ifdef DEBUG_RELEASE_ANGLE_MAPPING + std::cout << "Send down-release messages for note " << noteNumber_ << " on channel " << ch << "\n"; +#endif + // Send key switches: note on and note off in reverse orders + for(int i = 0; i < RELEASE_ANGLE_MAX_SEQUENCE_LENGTH; i++) { + if(downNotes_[i] != 0) + keyboard_.midiOutputController()->sendNoteOn(port, ch, downNotes_[i], downVelocities_[i]); + } + + for(int i = RELEASE_ANGLE_MAX_SEQUENCE_LENGTH - 1; i >= 0; i--) { + if(downNotes_[i] != 0) + keyboard_.midiOutputController()->sendNoteOff(port, ch, downNotes_[i]); + } + } + + // TODO: delayed release + #ifdef TROMBONE // KLUDGE: figure out how to do this more elegantly if(keyboard_.midiOutputController() != 0) {
--- a/Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMapping.h Wed Aug 27 13:18:27 2014 +0100 +++ b/Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMapping.h Wed Sep 24 00:29:18 2014 +0100 @@ -27,10 +27,14 @@ #include "../TouchkeyBaseMapping.h" +#define RELEASE_ANGLE_MAX_SEQUENCE_LENGTH 16 + // This class handles the detection of finger motion specifically at // note release, which can be used to trigger specific release effects. class TouchkeyReleaseAngleMapping : public TouchkeyBaseMapping { + friend class TouchkeyReleaseAngleMappingFactory; + private: // Default values /*constexpr static const int kDefaultFilterBufferLength = 30; @@ -39,6 +43,9 @@ static const int kDefaultFilterBufferLength; static const timestamp_diff_type kDefaultMaxLookbackTime; + static const float kDefaultUpMinimumAngle; + static const float kDefaultDownMinimumAngle; + public: // ***** Constructors ***** @@ -57,6 +64,17 @@ // Resend the current state of all parameters void resend(); + // Parameters for release angle algorithm + void setWindowSize(float windowSize); + void setUpMessagesEnabled(bool enable); + void setDownMessagesEnabled(bool enable); + void setUpMinimumAngle(float minAngle); + void setUpNote(int sequence, int note); + void setUpVelocity(int sequence, int velocity); + void setDownMinimumAngle(float minAngle); + void setDownNote(int sequence, int note); + void setDownVelocity(int sequence, int velocity); + // ***** Evaluators ***** // This method receives triggers whenever events occur in the touch data or the @@ -67,10 +85,13 @@ // This method handles the OSC message transmission. It should be run in the Scheduler // thread provided by PianoKeyboard. timestamp_type performMapping(); + + // Called when MIDI note release happens + void midiNoteOffReceived(int channel); // ***** Specific Methods ***** // Process the release by calculating the angle - void processRelease(timestamp_type timestamp); + void processRelease(/*timestamp_type timestamp*/); timestamp_type releaseKeySwitch(); @@ -81,6 +102,14 @@ // ***** Member Variables ***** + bool upEnabled_, downEnabled_; // Whether messages are enabled for upward and downward releases + float upMinimumAngle_; // Minimum release angle for trigger for up... + float downMinimumAngle_; // ...and down cases + int upNotes_[RELEASE_ANGLE_MAX_SEQUENCE_LENGTH]; // Notes and velocities to send on upward + int upVelocities_[RELEASE_ANGLE_MAX_SEQUENCE_LENGTH]; // and downward release + int downNotes_[RELEASE_ANGLE_MAX_SEQUENCE_LENGTH]; + int downVelocities_[RELEASE_ANGLE_MAX_SEQUENCE_LENGTH]; + Node<KeyTouchFrame> pastSamples_; // Locations of touch timestamp_diff_type maxLookbackTime_; // How long to look backwards to find release velocity CriticalSection sampleBufferMutex_; // Mutex to protect threaded access to sample buffer
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingExtendedEditor.cpp Wed Sep 24 00:29:18 2014 +0100 @@ -0,0 +1,785 @@ +/* + ============================================================================== + + This is an automatically generated GUI class created by the Introjucer! + + Be careful when adding custom code to these files, as only the code within + the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded + and re-saved. + + Created with Introjucer version: 3.1.0 + + ------------------------------------------------------------------------------ + + The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-13 by Raw Material Software Ltd. + + ============================================================================== +*/ + +//[Headers] You can add your own extra header files here... +//[/Headers] + +#include "TouchkeyReleaseAngleMappingExtendedEditor.h" + + +//[MiscUserDefs] You can add your own user definitions and misc code here... +//[/MiscUserDefs] + +//============================================================================== +TouchkeyReleaseAngleMappingExtendedEditor::TouchkeyReleaseAngleMappingExtendedEditor (TouchkeyReleaseAngleMappingFactory& factory) + : factory_(factory) +{ + addAndMakeVisible (titleLabel = new Label ("title label", + TRANS("Release Angle Mapping (Zone N, #M)"))); + titleLabel->setFont (Font (15.00f, Font::bold)); + titleLabel->setJustificationType (Justification::centredLeft); + titleLabel->setEditable (false, false, false); + titleLabel->setColour (TextEditor::textColourId, Colours::black); + titleLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (presetLabel = new Label ("preset label", + TRANS("Preset:"))); + presetLabel->setFont (Font (15.00f, Font::plain)); + presetLabel->setJustificationType (Justification::centredLeft); + presetLabel->setEditable (false, false, false); + presetLabel->setColour (TextEditor::textColourId, Colours::black); + presetLabel->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (presetComboBox = new ComboBox ("parameter combo box")); + presetComboBox->setEditableText (false); + presetComboBox->setJustificationType (Justification::centredLeft); + presetComboBox->setTextWhenNothingSelected (String::empty); + presetComboBox->setTextWhenNoChoicesAvailable (TRANS("(no choices)")); + presetComboBox->addListener (this); + + addAndMakeVisible (presetLabel2 = new Label ("preset label", + TRANS("Window Length:"))); + presetLabel2->setFont (Font (15.00f, Font::plain)); + presetLabel2->setJustificationType (Justification::centredLeft); + presetLabel2->setEditable (false, false, false); + presetLabel2->setColour (TextEditor::textColourId, Colours::black); + presetLabel2->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (windowLengthEditor = new TextEditor ("range low text editor")); + windowLengthEditor->setMultiLine (false); + windowLengthEditor->setReturnKeyStartsNewLine (false); + windowLengthEditor->setReadOnly (false); + windowLengthEditor->setScrollbarsShown (true); + windowLengthEditor->setCaretVisible (true); + windowLengthEditor->setPopupMenuEnabled (true); + windowLengthEditor->setText (String::empty); + + addAndMakeVisible (presetLabel3 = new Label ("preset label", + TRANS("ms. before release"))); + presetLabel3->setFont (Font (15.00f, Font::plain)); + presetLabel3->setJustificationType (Justification::centredLeft); + presetLabel3->setEditable (false, false, false); + presetLabel3->setColour (TextEditor::textColourId, Colours::black); + presetLabel3->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (presetLabel4 = new Label ("preset label", + TRANS("Release Moving Up"))); + presetLabel4->setFont (Font (15.00f, Font::bold)); + presetLabel4->setJustificationType (Justification::centredLeft); + presetLabel4->setEditable (false, false, false); + presetLabel4->setColour (TextEditor::textColourId, Colours::black); + presetLabel4->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (upMinSpeedEditor = new TextEditor ("up release speed editor")); + upMinSpeedEditor->setMultiLine (false); + upMinSpeedEditor->setReturnKeyStartsNewLine (false); + upMinSpeedEditor->setReadOnly (false); + upMinSpeedEditor->setScrollbarsShown (true); + upMinSpeedEditor->setCaretVisible (true); + upMinSpeedEditor->setPopupMenuEnabled (true); + upMinSpeedEditor->setText (String::empty); + + addAndMakeVisible (presetLabel5 = new Label ("preset label", + TRANS("Min. release speed:"))); + presetLabel5->setFont (Font (15.00f, Font::plain)); + presetLabel5->setJustificationType (Justification::centredRight); + presetLabel5->setEditable (false, false, false); + presetLabel5->setColour (TextEditor::textColourId, Colours::black); + presetLabel5->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (upNote1Editor = new TextEditor ("up note 1 editor")); + upNote1Editor->setMultiLine (false); + upNote1Editor->setReturnKeyStartsNewLine (false); + upNote1Editor->setReadOnly (false); + upNote1Editor->setScrollbarsShown (true); + upNote1Editor->setCaretVisible (true); + upNote1Editor->setPopupMenuEnabled (true); + upNote1Editor->setText (String::empty); + + addAndMakeVisible (presetLabel6 = new Label ("preset label", + TRANS("Send notes:"))); + presetLabel6->setFont (Font (15.00f, Font::plain)); + presetLabel6->setJustificationType (Justification::centredRight); + presetLabel6->setEditable (false, false, false); + presetLabel6->setColour (TextEditor::textColourId, Colours::black); + presetLabel6->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (upNote2Editor = new TextEditor ("up note 2 editor")); + upNote2Editor->setMultiLine (false); + upNote2Editor->setReturnKeyStartsNewLine (false); + upNote2Editor->setReadOnly (false); + upNote2Editor->setScrollbarsShown (true); + upNote2Editor->setCaretVisible (true); + upNote2Editor->setPopupMenuEnabled (true); + upNote2Editor->setText (String::empty); + + addAndMakeVisible (upNote3Editor = new TextEditor ("up note 3 editor")); + upNote3Editor->setMultiLine (false); + upNote3Editor->setReturnKeyStartsNewLine (false); + upNote3Editor->setReadOnly (false); + upNote3Editor->setScrollbarsShown (true); + upNote3Editor->setCaretVisible (true); + upNote3Editor->setPopupMenuEnabled (true); + upNote3Editor->setText (String::empty); + + addAndMakeVisible (presetLabel7 = new Label ("preset label", + TRANS("With velocities:"))); + presetLabel7->setFont (Font (15.00f, Font::plain)); + presetLabel7->setJustificationType (Justification::centredRight); + presetLabel7->setEditable (false, false, false); + presetLabel7->setColour (TextEditor::textColourId, Colours::black); + presetLabel7->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (upVelocity1Editor = new TextEditor ("up velocity 1 editor")); + upVelocity1Editor->setMultiLine (false); + upVelocity1Editor->setReturnKeyStartsNewLine (false); + upVelocity1Editor->setReadOnly (false); + upVelocity1Editor->setScrollbarsShown (true); + upVelocity1Editor->setCaretVisible (true); + upVelocity1Editor->setPopupMenuEnabled (true); + upVelocity1Editor->setText (String::empty); + + addAndMakeVisible (upVelocity2Editor = new TextEditor ("up velocity 2 editor")); + upVelocity2Editor->setMultiLine (false); + upVelocity2Editor->setReturnKeyStartsNewLine (false); + upVelocity2Editor->setReadOnly (false); + upVelocity2Editor->setScrollbarsShown (true); + upVelocity2Editor->setCaretVisible (true); + upVelocity2Editor->setPopupMenuEnabled (true); + upVelocity2Editor->setText (String::empty); + + addAndMakeVisible (upVelocity3Editor = new TextEditor ("up velocity 3 editor")); + upVelocity3Editor->setMultiLine (false); + upVelocity3Editor->setReturnKeyStartsNewLine (false); + upVelocity3Editor->setReadOnly (false); + upVelocity3Editor->setScrollbarsShown (true); + upVelocity3Editor->setCaretVisible (true); + upVelocity3Editor->setPopupMenuEnabled (true); + upVelocity3Editor->setText (String::empty); + + addAndMakeVisible (presetLabel8 = new Label ("preset label", + TRANS("Release Moving Down"))); + presetLabel8->setFont (Font (15.00f, Font::bold)); + presetLabel8->setJustificationType (Justification::centredLeft); + presetLabel8->setEditable (false, false, false); + presetLabel8->setColour (TextEditor::textColourId, Colours::black); + presetLabel8->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (downMinSpeedEditor = new TextEditor ("down release speed editor")); + downMinSpeedEditor->setMultiLine (false); + downMinSpeedEditor->setReturnKeyStartsNewLine (false); + downMinSpeedEditor->setReadOnly (false); + downMinSpeedEditor->setScrollbarsShown (true); + downMinSpeedEditor->setCaretVisible (true); + downMinSpeedEditor->setPopupMenuEnabled (true); + downMinSpeedEditor->setText (String::empty); + + addAndMakeVisible (presetLabel9 = new Label ("preset label", + TRANS("Min. release speed:"))); + presetLabel9->setFont (Font (15.00f, Font::plain)); + presetLabel9->setJustificationType (Justification::centredRight); + presetLabel9->setEditable (false, false, false); + presetLabel9->setColour (TextEditor::textColourId, Colours::black); + presetLabel9->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (downNote1Editor = new TextEditor ("down note 1 editor")); + downNote1Editor->setMultiLine (false); + downNote1Editor->setReturnKeyStartsNewLine (false); + downNote1Editor->setReadOnly (false); + downNote1Editor->setScrollbarsShown (true); + downNote1Editor->setCaretVisible (true); + downNote1Editor->setPopupMenuEnabled (true); + downNote1Editor->setText (String::empty); + + addAndMakeVisible (presetLabel10 = new Label ("preset label", + TRANS("Send notes:"))); + presetLabel10->setFont (Font (15.00f, Font::plain)); + presetLabel10->setJustificationType (Justification::centredRight); + presetLabel10->setEditable (false, false, false); + presetLabel10->setColour (TextEditor::textColourId, Colours::black); + presetLabel10->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (downNote2Editor = new TextEditor ("down note 2 editor")); + downNote2Editor->setMultiLine (false); + downNote2Editor->setReturnKeyStartsNewLine (false); + downNote2Editor->setReadOnly (false); + downNote2Editor->setScrollbarsShown (true); + downNote2Editor->setCaretVisible (true); + downNote2Editor->setPopupMenuEnabled (true); + downNote2Editor->setText (String::empty); + + addAndMakeVisible (downNote3Editor = new TextEditor ("down note 3 editor")); + downNote3Editor->setMultiLine (false); + downNote3Editor->setReturnKeyStartsNewLine (false); + downNote3Editor->setReadOnly (false); + downNote3Editor->setScrollbarsShown (true); + downNote3Editor->setCaretVisible (true); + downNote3Editor->setPopupMenuEnabled (true); + downNote3Editor->setText (String::empty); + + addAndMakeVisible (presetLabel11 = new Label ("preset label", + TRANS("With velocities:"))); + presetLabel11->setFont (Font (15.00f, Font::plain)); + presetLabel11->setJustificationType (Justification::centredRight); + presetLabel11->setEditable (false, false, false); + presetLabel11->setColour (TextEditor::textColourId, Colours::black); + presetLabel11->setColour (TextEditor::backgroundColourId, Colour (0x00000000)); + + addAndMakeVisible (downVelocity1Editor = new TextEditor ("down velocity 1 editor")); + downVelocity1Editor->setMultiLine (false); + downVelocity1Editor->setReturnKeyStartsNewLine (false); + downVelocity1Editor->setReadOnly (false); + downVelocity1Editor->setScrollbarsShown (true); + downVelocity1Editor->setCaretVisible (true); + downVelocity1Editor->setPopupMenuEnabled (true); + downVelocity1Editor->setText (String::empty); + + addAndMakeVisible (downVelocity2Editor = new TextEditor ("down velocity 2 editor")); + downVelocity2Editor->setMultiLine (false); + downVelocity2Editor->setReturnKeyStartsNewLine (false); + downVelocity2Editor->setReadOnly (false); + downVelocity2Editor->setScrollbarsShown (true); + downVelocity2Editor->setCaretVisible (true); + downVelocity2Editor->setPopupMenuEnabled (true); + downVelocity2Editor->setText (String::empty); + + addAndMakeVisible (downVelocity3Editor = new TextEditor ("down velocity 3 editor")); + downVelocity3Editor->setMultiLine (false); + downVelocity3Editor->setReturnKeyStartsNewLine (false); + downVelocity3Editor->setReadOnly (false); + downVelocity3Editor->setScrollbarsShown (true); + downVelocity3Editor->setCaretVisible (true); + downVelocity3Editor->setPopupMenuEnabled (true); + downVelocity3Editor->setText (String::empty); + + addAndMakeVisible (upEnableButton = new ToggleButton ("up enable button")); + upEnableButton->setButtonText (TRANS("Enable")); + upEnableButton->addListener (this); + + addAndMakeVisible (downEnableButton = new ToggleButton ("down enable button")); + downEnableButton->setButtonText (TRANS("Enable")); + downEnableButton->addListener (this); + + + //[UserPreSize] + for(int i = 0; i < factory_.getNumConfigurations(); i++) { + presetComboBox->addItem(factory_.getConfigurationName(i).c_str(), i+1); + } + + windowLengthEditor->addListener(this); + upMinSpeedEditor->addListener(this); + downMinSpeedEditor->addListener(this); + upNote1Editor->addListener(this); + upNote2Editor->addListener(this); + upNote3Editor->addListener(this); + upVelocity1Editor->addListener(this); + upVelocity2Editor->addListener(this); + upVelocity3Editor->addListener(this); + downNote1Editor->addListener(this); + downNote2Editor->addListener(this); + downNote3Editor->addListener(this); + downVelocity1Editor->addListener(this); + downVelocity2Editor->addListener(this); + downVelocity3Editor->addListener(this); + //[/UserPreSize] + + setSize (342, 328); + + + //[Constructor] You can add your own custom stuff here.. + //[/Constructor] +} + +TouchkeyReleaseAngleMappingExtendedEditor::~TouchkeyReleaseAngleMappingExtendedEditor() +{ + //[Destructor_pre]. You can add your own custom destruction code here.. + //[/Destructor_pre] + + titleLabel = nullptr; + presetLabel = nullptr; + presetComboBox = nullptr; + presetLabel2 = nullptr; + windowLengthEditor = nullptr; + presetLabel3 = nullptr; + presetLabel4 = nullptr; + upMinSpeedEditor = nullptr; + presetLabel5 = nullptr; + upNote1Editor = nullptr; + presetLabel6 = nullptr; + upNote2Editor = nullptr; + upNote3Editor = nullptr; + presetLabel7 = nullptr; + upVelocity1Editor = nullptr; + upVelocity2Editor = nullptr; + upVelocity3Editor = nullptr; + presetLabel8 = nullptr; + downMinSpeedEditor = nullptr; + presetLabel9 = nullptr; + downNote1Editor = nullptr; + presetLabel10 = nullptr; + downNote2Editor = nullptr; + downNote3Editor = nullptr; + presetLabel11 = nullptr; + downVelocity1Editor = nullptr; + downVelocity2Editor = nullptr; + downVelocity3Editor = nullptr; + upEnableButton = nullptr; + downEnableButton = nullptr; + + + //[Destructor]. You can add your own custom destruction code here.. + //[/Destructor] +} + +//============================================================================== +void TouchkeyReleaseAngleMappingExtendedEditor::paint (Graphics& g) +{ + //[UserPrePaint] Add your own custom painting code here.. + //[/UserPrePaint] + + g.fillAll (Colour (0xffd2d2d2)); + + //[UserPaint] Add your own custom painting code here.. + //[/UserPaint] +} + +void TouchkeyReleaseAngleMappingExtendedEditor::resized() +{ + titleLabel->setBounds (8, 8, 424, 24); + presetLabel->setBounds (8, 40, 56, 24); + presetComboBox->setBounds (64, 40, 264, 24); + presetLabel2->setBounds (8, 80, 112, 24); + windowLengthEditor->setBounds (120, 80, 56, 24); + presetLabel3->setBounds (176, 80, 136, 24); + presetLabel4->setBounds (8, 112, 136, 24); + upMinSpeedEditor->setBounds (144, 136, 56, 24); + presetLabel5->setBounds (8, 136, 136, 24); + upNote1Editor->setBounds (144, 160, 56, 24); + presetLabel6->setBounds (8, 160, 136, 24); + upNote2Editor->setBounds (208, 160, 56, 24); + upNote3Editor->setBounds (272, 160, 56, 24); + presetLabel7->setBounds (8, 184, 136, 24); + upVelocity1Editor->setBounds (144, 184, 56, 24); + upVelocity2Editor->setBounds (208, 184, 56, 24); + upVelocity3Editor->setBounds (272, 184, 56, 24); + presetLabel8->setBounds (8, 216, 160, 24); + downMinSpeedEditor->setBounds (144, 240, 56, 24); + presetLabel9->setBounds (8, 240, 136, 24); + downNote1Editor->setBounds (144, 264, 56, 24); + presetLabel10->setBounds (8, 264, 136, 24); + downNote2Editor->setBounds (208, 264, 56, 24); + downNote3Editor->setBounds (272, 264, 56, 24); + presetLabel11->setBounds (8, 288, 136, 24); + downVelocity1Editor->setBounds (144, 288, 56, 24); + downVelocity2Editor->setBounds (208, 288, 56, 24); + downVelocity3Editor->setBounds (272, 288, 56, 24); + upEnableButton->setBounds (208, 112, 72, 24); + downEnableButton->setBounds (208, 216, 72, 24); + //[UserResized] Add your own custom resize handling here.. + //[/UserResized] +} + +void TouchkeyReleaseAngleMappingExtendedEditor::comboBoxChanged (ComboBox* comboBoxThatHasChanged) +{ + //[UsercomboBoxChanged_Pre] + //[/UsercomboBoxChanged_Pre] + + if (comboBoxThatHasChanged == presetComboBox) + { + //[UserComboBoxCode_presetComboBox] -- add your combo box handling code here.. + int index = presetComboBox->getSelectedItemIndex(); + factory_.setCurrentConfiguration(index); + //[/UserComboBoxCode_presetComboBox] + } + + //[UsercomboBoxChanged_Post] + //[/UsercomboBoxChanged_Post] +} + +void TouchkeyReleaseAngleMappingExtendedEditor::buttonClicked (Button* buttonThatWasClicked) +{ + //[UserbuttonClicked_Pre] + //[/UserbuttonClicked_Pre] + + if (buttonThatWasClicked == upEnableButton) + { + //[UserButtonCode_upEnableButton] -- add your button handler code here.. + factory_.setUpMessagesEnabled(upEnableButton->getToggleState()); + //[/UserButtonCode_upEnableButton] + } + else if (buttonThatWasClicked == downEnableButton) + { + //[UserButtonCode_downEnableButton] -- add your button handler code here.. + factory_.setDownMessagesEnabled(downEnableButton->getToggleState()); + //[/UserButtonCode_downEnableButton] + } + + //[UserbuttonClicked_Post] + //[/UserbuttonClicked_Post] +} + + + +//[MiscUserCode] You can add your own definitions of your custom methods or any other code here... + +void TouchkeyReleaseAngleMappingExtendedEditor::textEditorReturnKeyPressed(TextEditor &editor) +{ + if(&editor == windowLengthEditor) { + float windowLength = atof(windowLengthEditor->getText().toUTF8()); + factory_.setWindowSize(windowLength); + } + else if(&editor == upMinSpeedEditor) { + float speed = atof(upMinSpeedEditor->getText().toUTF8()); + factory_.setUpMinimumAngle(speed); + } + else if(&editor == downMinSpeedEditor) { + float speed = atof(downMinSpeedEditor->getText().toUTF8()); + factory_.setDownMinimumAngle(speed); + } + else { + // All the other editors are int values + int value = atoi(editor.getText().toUTF8()); + + if(&editor == upNote1Editor) + factory_.setUpNote(0, value); + else if(&editor == upNote2Editor) + factory_.setUpNote(1, value); + else if(&editor == upNote3Editor) + factory_.setUpNote(2, value); + else if(&editor == upVelocity1Editor) + factory_.setUpVelocity(0, value); + else if(&editor == upVelocity2Editor) + factory_.setUpVelocity(1, value); + else if(&editor == upVelocity3Editor) + factory_.setUpVelocity(2, value); + else if(&editor == downNote1Editor) + factory_.setDownNote(0, value); + else if(&editor == downNote2Editor) + factory_.setDownNote(1, value); + else if(&editor == downNote3Editor) + factory_.setDownNote(2, value); + else if(&editor == downVelocity1Editor) + factory_.setDownVelocity(0, value); + else if(&editor == downVelocity2Editor) + factory_.setDownVelocity(1, value); + else if(&editor == downVelocity3Editor) + factory_.setDownVelocity(2, value); + } +} + +void TouchkeyReleaseAngleMappingExtendedEditor::textEditorEscapeKeyPressed(TextEditor &editor) +{ + +} + +void TouchkeyReleaseAngleMappingExtendedEditor::textEditorFocusLost(TextEditor &editor) +{ + textEditorReturnKeyPressed(editor); +} + +void TouchkeyReleaseAngleMappingExtendedEditor::synchronize() +{ + // Set the title label + titleLabel->setText(getDescriptionHelper("Release Angle Mapping"), dontSendNotification); + + // Update the editors to reflect the current status + if(!windowLengthEditor->hasKeyboardFocus(true)) { + float value = factory_.getWindowSize(); + char st[16]; +#ifdef _MSC_VER + _snprintf_s(st, 16, _TRUNCATE, "%.0f", value); +#else + snprintf(st, 16, "%.0f", value); +#endif + windowLengthEditor->setText(st); + } + + if(!upMinSpeedEditor->hasKeyboardFocus(true)) { + float value = factory_.getUpMinimumAngle(); + char st[16]; +#ifdef _MSC_VER + _snprintf_s(st, 16, _TRUNCATE, "%.2f", value); +#else + snprintf(st, 16, "%.2f", value); +#endif + + upMinSpeedEditor->setText(st); + } + + if(!downMinSpeedEditor->hasKeyboardFocus(true)) { + float value = factory_.getDownMinimumAngle(); + char st[16]; +#ifdef _MSC_VER + _snprintf_s(st, 16, _TRUNCATE, "%.2f", value); +#else + snprintf(st, 16, "%.2f", value); +#endif + + downMinSpeedEditor->setText(st); + } + + char st[16]; + + if(!upNote1Editor->hasKeyboardFocus(true)) { + intToString(st, factory_.getUpNote(0)); + upNote1Editor->setText(st); + } + if(!upNote2Editor->hasKeyboardFocus(true)) { + intToString(st, factory_.getUpNote(1)); + upNote2Editor->setText(st); + } + if(!upNote3Editor->hasKeyboardFocus(true)) { + intToString(st, factory_.getUpNote(2)); + upNote3Editor->setText(st); + } + if(!upVelocity1Editor->hasKeyboardFocus(true)) { + intToString(st, factory_.getUpVelocity(0)); + upVelocity1Editor->setText(st); + } + if(!upVelocity2Editor->hasKeyboardFocus(true)) { + intToString(st, factory_.getUpVelocity(1)); + upVelocity2Editor->setText(st); + } + if(!upVelocity3Editor->hasKeyboardFocus(true)) { + intToString(st, factory_.getUpVelocity(2)); + upVelocity3Editor->setText(st); + } + if(!downNote1Editor->hasKeyboardFocus(true)) { + intToString(st, factory_.getDownNote(0)); + downNote1Editor->setText(st); + } + if(!downNote2Editor->hasKeyboardFocus(true)) { + intToString(st, factory_.getDownNote(1)); + downNote2Editor->setText(st); + } + if(!downNote3Editor->hasKeyboardFocus(true)) { + intToString(st, factory_.getDownNote(2)); + downNote3Editor->setText(st); + } + if(!downVelocity1Editor->hasKeyboardFocus(true)) { + intToString(st, factory_.getDownVelocity(0)); + downVelocity1Editor->setText(st); + } + if(!downVelocity2Editor->hasKeyboardFocus(true)) { + intToString(st, factory_.getDownVelocity(1)); + downVelocity2Editor->setText(st); + } + if(!downVelocity3Editor->hasKeyboardFocus(true)) { + intToString(st, factory_.getDownVelocity(2)); + downVelocity3Editor->setText(st); + } + + upEnableButton->setToggleState(factory_.getUpMessagesEnabled(), dontSendNotification); + downEnableButton->setToggleState(factory_.getDownMessageEnabled(), dontSendNotification); + + int configuration = factory_.getCurrentConfiguration(); + if(configuration >= 0) + presetComboBox->setSelectedItemIndex(configuration, dontSendNotification); + else + presetComboBox->setText(""); +} + +// Return a human-readable description of this mapping for the window +String TouchkeyReleaseAngleMappingExtendedEditor::getDescription() { + return getDescriptionHelper("Release Angle"); +} + +// Return a human-readable description of this mapping for the window +String TouchkeyReleaseAngleMappingExtendedEditor::getDescriptionHelper(String baseName) { + String desc = baseName; + + desc += " (Zone "; + + int zone = factory_.segment().outputPort(); + desc += zone; + desc += ", #"; + + int mappingNumber = factory_.segment().indexOfMappingFactory(&factory_); + desc += mappingNumber; + desc += ")"; + + return desc; +} + +// Cross-platform helper function to deal with weird Visual Studio definitions... +void TouchkeyReleaseAngleMappingExtendedEditor::intToString(char *st, int value) { +#ifdef _MSC_VER + _snprintf_s(st, 16, _TRUNCATE, "%d", value); +#else + snprintf(st, 16, "%d", value); +#endif +} + +//[/MiscUserCode] + + +//============================================================================== +#if 0 +/* -- Introjucer information section -- + + This is where the Introjucer stores the metadata that describe this GUI layout, so + make changes in here at your peril! + +BEGIN_JUCER_METADATA + +<JUCER_COMPONENT documentType="Component" className="TouchkeyReleaseAngleMappingExtendedEditor" + componentName="" parentClasses="public MappingEditorComponent, public TextEditor::Listener" + constructorParams="TouchkeyReleaseAngleMappingFactory& factory" + variableInitialisers="factory_(factory)" snapPixels="8" snapActive="1" + snapShown="1" overlayOpacity="0.330" fixedSize="1" initialWidth="342" + initialHeight="328"> + <BACKGROUND backgroundColour="ffd2d2d2"/> + <LABEL name="title label" id="2346b62ce034bea2" memberName="titleLabel" + virtualName="" explicitFocusOrder="0" pos="8 8 424 24" edTextCol="ff000000" + edBkgCol="0" labelText="Release Angle Mapping (Zone N, #M)" editableSingleClick="0" + editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font" + fontsize="15" bold="1" italic="0" justification="33"/> + <LABEL name="preset label" id="5ef7c1b78fdcf616" memberName="presetLabel" + virtualName="" explicitFocusOrder="0" pos="8 40 56 24" edTextCol="ff000000" + edBkgCol="0" labelText="Preset:" editableSingleClick="0" editableDoubleClick="0" + focusDiscardsChanges="0" fontname="Default font" fontsize="15" + bold="0" italic="0" justification="33"/> + <COMBOBOX name="parameter combo box" id="f12f6f6e31042be1" memberName="presetComboBox" + virtualName="" explicitFocusOrder="0" pos="64 40 264 24" editable="0" + layout="33" items="" textWhenNonSelected="" textWhenNoItems="(no choices)"/> + <LABEL name="preset label" id="6c7fb9cdad1ef615" memberName="presetLabel2" + virtualName="" explicitFocusOrder="0" pos="8 80 112 24" edTextCol="ff000000" + edBkgCol="0" labelText="Window Length:" editableSingleClick="0" + editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font" + fontsize="15" bold="0" italic="0" justification="33"/> + <TEXTEDITOR name="range low text editor" id="db0f62c03a58af03" memberName="windowLengthEditor" + virtualName="" explicitFocusOrder="0" pos="120 80 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <LABEL name="preset label" id="bf72fc0576275cec" memberName="presetLabel3" + virtualName="" explicitFocusOrder="0" pos="176 80 136 24" edTextCol="ff000000" + edBkgCol="0" labelText="ms. before release" editableSingleClick="0" + editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font" + fontsize="15" bold="0" italic="0" justification="33"/> + <LABEL name="preset label" id="737ac0c84cd35f2a" memberName="presetLabel4" + virtualName="" explicitFocusOrder="0" pos="8 112 136 24" edTextCol="ff000000" + edBkgCol="0" labelText="Release Moving Up" editableSingleClick="0" + editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font" + fontsize="15" bold="1" italic="0" justification="33"/> + <TEXTEDITOR name="up release speed editor" id="6d12507cf2b05308" memberName="upMinSpeedEditor" + virtualName="" explicitFocusOrder="0" pos="144 136 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <LABEL name="preset label" id="4bf2ba2e74c7f918" memberName="presetLabel5" + virtualName="" explicitFocusOrder="0" pos="8 136 136 24" edTextCol="ff000000" + edBkgCol="0" labelText="Min. release speed:" editableSingleClick="0" + editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font" + fontsize="15" bold="0" italic="0" justification="34"/> + <TEXTEDITOR name="up note 1 editor" id="48bc9cb4bc2b66d7" memberName="upNote1Editor" + virtualName="" explicitFocusOrder="0" pos="144 160 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <LABEL name="preset label" id="e98f51307ccd3213" memberName="presetLabel6" + virtualName="" explicitFocusOrder="0" pos="8 160 136 24" edTextCol="ff000000" + edBkgCol="0" labelText="Send notes:" editableSingleClick="0" + editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font" + fontsize="15" bold="0" italic="0" justification="34"/> + <TEXTEDITOR name="up note 2 editor" id="a1078ce66401fa26" memberName="upNote2Editor" + virtualName="" explicitFocusOrder="0" pos="208 160 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <TEXTEDITOR name="up note 3 editor" id="3b6be211e2c57644" memberName="upNote3Editor" + virtualName="" explicitFocusOrder="0" pos="272 160 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <LABEL name="preset label" id="cd890cf41d7607bd" memberName="presetLabel7" + virtualName="" explicitFocusOrder="0" pos="8 184 136 24" edTextCol="ff000000" + edBkgCol="0" labelText="With velocities:" editableSingleClick="0" + editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font" + fontsize="15" bold="0" italic="0" justification="34"/> + <TEXTEDITOR name="up velocity 1 editor" id="47d3d530ed72615a" memberName="upVelocity1Editor" + virtualName="" explicitFocusOrder="0" pos="144 184 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <TEXTEDITOR name="up velocity 2 editor" id="ff6d7b8e5b4a5bd6" memberName="upVelocity2Editor" + virtualName="" explicitFocusOrder="0" pos="208 184 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <TEXTEDITOR name="up velocity 3 editor" id="65dabffb4ac41d8d" memberName="upVelocity3Editor" + virtualName="" explicitFocusOrder="0" pos="272 184 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <LABEL name="preset label" id="f8444692065e742a" memberName="presetLabel8" + virtualName="" explicitFocusOrder="0" pos="8 216 160 24" edTextCol="ff000000" + edBkgCol="0" labelText="Release Moving Down" editableSingleClick="0" + editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font" + fontsize="15" bold="1" italic="0" justification="33"/> + <TEXTEDITOR name="down release speed editor" id="4d87b35c1bd38cfd" memberName="downMinSpeedEditor" + virtualName="" explicitFocusOrder="0" pos="144 240 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <LABEL name="preset label" id="cfa916d2ffe4090d" memberName="presetLabel9" + virtualName="" explicitFocusOrder="0" pos="8 240 136 24" edTextCol="ff000000" + edBkgCol="0" labelText="Min. release speed:" editableSingleClick="0" + editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font" + fontsize="15" bold="0" italic="0" justification="34"/> + <TEXTEDITOR name="down note 1 editor" id="fe8e24594d26ec2d" memberName="downNote1Editor" + virtualName="" explicitFocusOrder="0" pos="144 264 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <LABEL name="preset label" id="56bc59cd5ceb0e2" memberName="presetLabel10" + virtualName="" explicitFocusOrder="0" pos="8 264 136 24" edTextCol="ff000000" + edBkgCol="0" labelText="Send notes:" editableSingleClick="0" + editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font" + fontsize="15" bold="0" italic="0" justification="34"/> + <TEXTEDITOR name="down note 2 editor" id="e0088e60d93fd53" memberName="downNote2Editor" + virtualName="" explicitFocusOrder="0" pos="208 264 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <TEXTEDITOR name="down note 3 editor" id="23571b41edd72631" memberName="downNote3Editor" + virtualName="" explicitFocusOrder="0" pos="272 264 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <LABEL name="preset label" id="a62bc5524128106c" memberName="presetLabel11" + virtualName="" explicitFocusOrder="0" pos="8 288 136 24" edTextCol="ff000000" + edBkgCol="0" labelText="With velocities:" editableSingleClick="0" + editableDoubleClick="0" focusDiscardsChanges="0" fontname="Default font" + fontsize="15" bold="0" italic="0" justification="34"/> + <TEXTEDITOR name="down velocity 1 editor" id="f4a94019655ea3ab" memberName="downVelocity1Editor" + virtualName="" explicitFocusOrder="0" pos="144 288 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <TEXTEDITOR name="down velocity 2 editor" id="b2c75ef9c586a2e2" memberName="downVelocity2Editor" + virtualName="" explicitFocusOrder="0" pos="208 288 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <TEXTEDITOR name="down velocity 3 editor" id="96bf0ea9075d357f" memberName="downVelocity3Editor" + virtualName="" explicitFocusOrder="0" pos="272 288 56 24" initialText="" + multiline="0" retKeyStartsLine="0" readonly="0" scrollbars="1" + caret="1" popupmenu="1"/> + <TOGGLEBUTTON name="up enable button" id="d3cb9267f9296315" memberName="upEnableButton" + virtualName="" explicitFocusOrder="0" pos="208 112 72 24" buttonText="Enable" + connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/> + <TOGGLEBUTTON name="down enable button" id="59af46c3b5431919" memberName="downEnableButton" + virtualName="" explicitFocusOrder="0" pos="208 216 72 24" buttonText="Enable" + connectedEdges="0" needsCallback="1" radioGroupId="0" state="0"/> +</JUCER_COMPONENT> + +END_JUCER_METADATA +*/ +#endif + + +//[EndFile] You can add extra defines here... +//[/EndFile]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingExtendedEditor.h Wed Sep 24 00:29:18 2014 +0100 @@ -0,0 +1,115 @@ +/* + ============================================================================== + + This is an automatically generated GUI class created by the Introjucer! + + Be careful when adding custom code to these files, as only the code within + the "//[xyz]" and "//[/xyz]" sections will be retained when the file is loaded + and re-saved. + + Created with Introjucer version: 3.1.0 + + ------------------------------------------------------------------------------ + + The Introjucer is part of the JUCE library - "Jules' Utility Class Extensions" + Copyright 2004-13 by Raw Material Software Ltd. + + ============================================================================== +*/ + +#ifndef __JUCE_HEADER_24D73157539FBFD0__ +#define __JUCE_HEADER_24D73157539FBFD0__ + +//[Headers] -- You can add your own extra header files here -- +#include "JuceHeader.h" +#include "TouchkeyReleaseAngleMappingFactory.h" +//[/Headers] + + + +//============================================================================== +/** + //[Comments] + An auto-generated component, created by the Introjucer. + + Describe your class and how it works here! + //[/Comments] +*/ +class TouchkeyReleaseAngleMappingExtendedEditor : public MappingEditorComponent, + public TextEditor::Listener, + public ComboBoxListener, + public ButtonListener +{ +public: + //============================================================================== + TouchkeyReleaseAngleMappingExtendedEditor (TouchkeyReleaseAngleMappingFactory& factory); + ~TouchkeyReleaseAngleMappingExtendedEditor(); + + //============================================================================== + //[UserMethods] -- You can add your own custom methods in this section. + void textEditorTextChanged(TextEditor &editor) {} + void textEditorReturnKeyPressed(TextEditor &editor); + void textEditorEscapeKeyPressed(TextEditor &editor); + void textEditorFocusLost(TextEditor &editor); + + void synchronize(); + String getDescription(); + //[/UserMethods] + + void paint (Graphics& g); + void resized(); + void comboBoxChanged (ComboBox* comboBoxThatHasChanged); + void buttonClicked (Button* buttonThatWasClicked); + + + +private: + //[UserVariables] -- You can add your own custom variables in this section. + void intToString(char *st, int value); + + String getDescriptionHelper(String baseName); + + TouchkeyReleaseAngleMappingFactory& factory_; + //[/UserVariables] + + //============================================================================== + ScopedPointer<Label> titleLabel; + ScopedPointer<Label> presetLabel; + ScopedPointer<ComboBox> presetComboBox; + ScopedPointer<Label> presetLabel2; + ScopedPointer<TextEditor> windowLengthEditor; + ScopedPointer<Label> presetLabel3; + ScopedPointer<Label> presetLabel4; + ScopedPointer<TextEditor> upMinSpeedEditor; + ScopedPointer<Label> presetLabel5; + ScopedPointer<TextEditor> upNote1Editor; + ScopedPointer<Label> presetLabel6; + ScopedPointer<TextEditor> upNote2Editor; + ScopedPointer<TextEditor> upNote3Editor; + ScopedPointer<Label> presetLabel7; + ScopedPointer<TextEditor> upVelocity1Editor; + ScopedPointer<TextEditor> upVelocity2Editor; + ScopedPointer<TextEditor> upVelocity3Editor; + ScopedPointer<Label> presetLabel8; + ScopedPointer<TextEditor> downMinSpeedEditor; + ScopedPointer<Label> presetLabel9; + ScopedPointer<TextEditor> downNote1Editor; + ScopedPointer<Label> presetLabel10; + ScopedPointer<TextEditor> downNote2Editor; + ScopedPointer<TextEditor> downNote3Editor; + ScopedPointer<Label> presetLabel11; + ScopedPointer<TextEditor> downVelocity1Editor; + ScopedPointer<TextEditor> downVelocity2Editor; + ScopedPointer<TextEditor> downVelocity3Editor; + ScopedPointer<ToggleButton> upEnableButton; + ScopedPointer<ToggleButton> downEnableButton; + + + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TouchkeyReleaseAngleMappingExtendedEditor) +}; + +//[EndFile] You can add extra defines here... +//[/EndFile] + +#endif // __JUCE_HEADER_24D73157539FBFD0__
--- a/Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingFactory.cpp Wed Aug 27 13:18:27 2014 +0100 +++ b/Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingFactory.cpp Wed Sep 24 00:29:18 2014 +0100 @@ -23,13 +23,180 @@ */ #include "TouchkeyReleaseAngleMappingFactory.h" +#include "TouchkeyReleaseAngleMappingExtendedEditor.h" // Class constants const timestamp_diff_type TouchkeyReleaseAngleMappingFactory::kDefaultMaxLookbackTime = milliseconds_to_timestamp(100); - +const int TouchkeyReleaseAngleMappingFactory::kNumConfigurations = 2; +const std::string TouchkeyReleaseAngleMappingFactory::kConfigurationNames[] = { + "Sample Modeling Trombone", + "Sample Modeling Trumpet" +}; TouchkeyReleaseAngleMappingFactory::TouchkeyReleaseAngleMappingFactory(PianoKeyboard &keyboard, MidiKeyboardSegment& segment) -: TouchkeyBaseMappingFactory<TouchkeyReleaseAngleMapping>(keyboard, segment) {} +: TouchkeyBaseMappingFactory<TouchkeyReleaseAngleMapping>(keyboard, segment), +currentConfiguration_(-1), +upEnabled_(true), downEnabled_(true), +upMinimumAngle_(TouchkeyReleaseAngleMapping::kDefaultUpMinimumAngle), +downMinimumAngle_(TouchkeyReleaseAngleMapping::kDefaultDownMinimumAngle) +{ + // Get default values from the first configuration + setCurrentConfiguration(0); +} + +// Set a particular configuration; make sure the values here match the +// defined names and indices above +void TouchkeyReleaseAngleMappingFactory::setCurrentConfiguration(int index) { + if(index == 0) { + // Sample Modeling Trombone + currentConfiguration_ = 0; + upEnabled_ = downEnabled_ = true; + upMinimumAngle_ = 1.0; + downMinimumAngle_ = 1.5; + windowSizeMilliseconds_ = 100.0; + + clearNotes(); + + upNotes_[0] = 36; + upVelocities_[0] = 64; + upNotes_[1] = 31; + upVelocities_[1] = 96; + + downNotes_[0] = 36; + downVelocities_[0] = 64; + downNotes_[1] = 33; + downVelocities_[1] = 80; + } + else if(index == 1) { + // Sample Modeling Trumpet + currentConfiguration_ = 1; + upEnabled_ = downEnabled_ = true; + upMinimumAngle_ = 1.0; + downMinimumAngle_ = 1.5; + windowSizeMilliseconds_ = 100.0; + + clearNotes(); + + upNotes_[0] = 48; + upVelocities_[0] = 64; + upNotes_[1] = 42; + upVelocities_[1] = 96; + + downNotes_[0] = 48; + downVelocities_[0] = 64; + downNotes_[1] = 46; + downVelocities_[1] = 96; + } +} + +// Parameters for release angle algorithm +int TouchkeyReleaseAngleMappingFactory::getUpNote(int sequence) { + if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH) + return 0; + return upNotes_[sequence]; +} + +int TouchkeyReleaseAngleMappingFactory::getUpVelocity(int sequence) { + if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH) + return 0; + return upVelocities_[sequence]; +} + +int TouchkeyReleaseAngleMappingFactory::getDownNote(int sequence) { + if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH) + return 0; + return downNotes_[sequence]; +} + +int TouchkeyReleaseAngleMappingFactory::getDownVelocity(int sequence) { + if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH) + return 0; + return downVelocities_[sequence]; +} + +void TouchkeyReleaseAngleMappingFactory::setWindowSize(float windowSize) { + if(windowSizeMilliseconds_ != windowSize) + currentConfiguration_ = -1; + windowSizeMilliseconds_ = windowSize; +} + +void TouchkeyReleaseAngleMappingFactory::setUpMessagesEnabled(bool enable) { + if(upEnabled_ != enable) + currentConfiguration_ = -1; + upEnabled_ = enable; +} + +void TouchkeyReleaseAngleMappingFactory::setDownMessagesEnabled(bool enable) { + if(downEnabled_ != enable) + currentConfiguration_ = -1; + downEnabled_ = enable; +} + +void TouchkeyReleaseAngleMappingFactory::setUpMinimumAngle(float minAngle) { + if(upMinimumAngle_ != minAngle) + currentConfiguration_ = -1; + upMinimumAngle_ = fabsf(minAngle); +} + +void TouchkeyReleaseAngleMappingFactory::setUpNote(int sequence, int note) { + if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH) + return; + if(note < 0 || note > 127) + upNotes_[sequence] = 0; + else { + if(upNotes_[sequence] != note) + currentConfiguration_ = -1; + upNotes_[sequence] = note; + } +} + +void TouchkeyReleaseAngleMappingFactory::setUpVelocity(int sequence, int velocity) { + if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH) + return; + if(velocity < 0 || velocity > 127) + upVelocities_[sequence] = 0; + else { + if(upVelocities_[sequence] != velocity) + currentConfiguration_ = -1; + upVelocities_[sequence] = velocity; + } +} + +void TouchkeyReleaseAngleMappingFactory::setDownMinimumAngle(float minAngle) { + if(downMinimumAngle_ != minAngle) + currentConfiguration_ = -1; + downMinimumAngle_ = fabsf(minAngle); +} + +void TouchkeyReleaseAngleMappingFactory::setDownNote(int sequence, int note) { + if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH) + return; + if(note < 0 || note > 127) + downNotes_[sequence] = 0; + else { + if(downNotes_[sequence] != note) + currentConfiguration_ = -1; + downNotes_[sequence] = note; + } +} + +void TouchkeyReleaseAngleMappingFactory::setDownVelocity(int sequence, int velocity) { + if(sequence < 0 || sequence >= RELEASE_ANGLE_MAX_SEQUENCE_LENGTH) + return; + if(velocity < 0 || velocity > 127) + downVelocities_[sequence] = 0; + else { + if(downVelocities_[sequence] != velocity) + currentConfiguration_ = -1; + downVelocities_[sequence] = velocity; + } +} + +// ***** GUI Support ***** + +MappingEditorComponent* TouchkeyReleaseAngleMappingFactory::createExtendedEditor() { + return new TouchkeyReleaseAngleMappingExtendedEditor(*this); +} // ****** Preset Save/Load ****** XmlElement* TouchkeyReleaseAngleMappingFactory::getPreset() { @@ -37,7 +204,14 @@ storeCommonProperties(properties); - // No properties for now + properties.setValue("currentConfiguration", currentConfiguration_); + properties.setValue("upEnabled", upEnabled_); + properties.setValue("downEnabled", downEnabled_); + properties.setValue("upMinimumAngle", upMinimumAngle_); + properties.setValue("downMinimumAngle", downMinimumAngle_); + properties.setValue("windowSizeMilliseconds", windowSizeMilliseconds_); + + // TODO: set arrays of notes and velocities XmlElement* preset = properties.createXml("MappingFactory"); preset->setAttribute("type", "ReleaseAngle"); @@ -55,13 +229,37 @@ if(!loadCommonProperties(properties)) return false; - // Nothing specific to do for now + // First check if there's a default configuration in use + // We can get all other parameters from that regardless of the + // remaining contents + if(properties.containsKey("currentConfiguration")) { + int config = properties.getIntValue("currentConfiguration"); + if(config >= 0 && config < kNumConfigurations) + setCurrentConfiguration(config); + } + else { + if(!properties.containsKey("upEnabled") || + !properties.containsKey("downEnabled") || + !properties.containsKey("upMinimumAngle") || + !properties.containsKey("downMinimumAngle") || + !properties.containsKey("windowSizeMilliseconds")) + return false; + + currentConfiguration_ = -1; + upEnabled_ = properties.getBoolValue("upEnabled"); + downEnabled_ = properties.getBoolValue("downEnabled"); + upMinimumAngle_ = properties.getDoubleValue("upMinimumAngle"); + downMinimumAngle_ = properties.getDoubleValue("downMinimumAngle"); + windowSizeMilliseconds_ = properties.getDoubleValue("windowSizeMilliseconds"); + + // TODO: load arrays of notes and velocities + } return true; } // MIDI note ended: see whether the mapping was suspended and if not, execute the angle calculation -void TouchkeyReleaseAngleMappingFactory::midiNoteOff(int noteNumber, bool touchIsOn, bool keyMotionActive, +/*void TouchkeyReleaseAngleMappingFactory::midiNoteOff(int noteNumber, bool touchIsOn, bool keyMotionActive, Node<KeyTouchFrame>* touchBuffer, Node<key_position>* positionBuffer, KeyPositionTracker* positionTracker) { @@ -71,4 +269,26 @@ // Call base class method TouchkeyBaseMappingFactory<TouchkeyReleaseAngleMapping>::midiNoteOff(noteNumber, touchIsOn, keyMotionActive, touchBuffer, positionBuffer, positionTracker); +}*/ + +void TouchkeyReleaseAngleMappingFactory::initializeMappingParameters(int noteNumber, + TouchkeyReleaseAngleMapping *mapping) { + mapping->setWindowSize(windowSizeMilliseconds_); + mapping->setUpMessagesEnabled(upEnabled_); + mapping->setDownMessagesEnabled(downEnabled_); + mapping->setUpMinimumAngle(upMinimumAngle_); + mapping->setDownMinimumAngle(downMinimumAngle_); + + for(int i = 0; i < RELEASE_ANGLE_MAX_SEQUENCE_LENGTH; i++) { + mapping->setUpNote(i, upNotes_[i]); + mapping->setUpVelocity(i, upVelocities_[i]); + mapping->setDownNote(i, downNotes_[i]); + mapping->setDownVelocity(i, downVelocities_[i]); + } } + +// Reset notes and velocities to defaults +void TouchkeyReleaseAngleMappingFactory::clearNotes() { + for(int i = 0; i < RELEASE_ANGLE_MAX_SEQUENCE_LENGTH; i++) + upNotes_[i] = downNotes_[i] = upVelocities_[i] = downVelocities_[i] = 0; +}
--- a/Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingFactory.h Wed Aug 27 13:18:27 2014 +0100 +++ b/Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingFactory.h Wed Sep 24 00:29:18 2014 +0100 @@ -33,6 +33,9 @@ //constexpr static const timestamp_diff_type kDefaultMaxLookbackTime = milliseconds_to_timestamp(100); static const timestamp_diff_type kDefaultMaxLookbackTime; + static const int kNumConfigurations; + static const std::string kConfigurationNames[]; + public: // ***** Constructor ***** @@ -46,6 +49,50 @@ // ***** Accessors / Modifiers ***** virtual const std::string factoryTypeName() { return "Release\nAngle"; } + // ***** Specific Parameter Methods ***** + + float getWindowSize() { return windowSizeMilliseconds_; } + bool getUpMessagesEnabled() { return upEnabled_; } + bool getDownMessageEnabled() { return downEnabled_; } + float getUpMinimumAngle() { return upMinimumAngle_; } + int getUpNote(int sequence); + int getUpVelocity(int sequence); + float getDownMinimumAngle() { return downMinimumAngle_; } + int getDownNote(int sequence); + int getDownVelocity(int sequence); + + void setWindowSize(float windowSize); + void setUpMessagesEnabled(bool enable); + void setDownMessagesEnabled(bool enable); + void setUpMinimumAngle(float minAngle); + void setUpNote(int sequence, int note); + void setUpVelocity(int sequence, int velocity); + void setDownMinimumAngle(float minAngle); + void setDownNote(int sequence, int note); + void setDownVelocity(int sequence, int velocity); + + // Methods for loading release-angle specific preset settings (different from the + // global preset methdos which are for save/load of files) + + int getNumConfigurations() { return kNumConfigurations; } + std::string getConfigurationName(int index) { + if(index < 0 || index >= kNumConfigurations) + return ""; + return kConfigurationNames[index]; + } + + // Returns current configuration or -1 if not a default setting + int getCurrentConfiguration() { + return currentConfiguration_; + } + void setCurrentConfiguration(int index); + + // ***** GUI Support ***** + bool hasBasicEditor() { return false; } + MappingEditorComponent* createBasicEditor() { return nullptr; } + bool hasExtendedEditor() { return true; } + MappingEditorComponent* createExtendedEditor(); + // ****** Preset Save/Load ****** XmlElement* getPreset(); bool loadPreset(XmlElement const* preset); @@ -53,11 +100,27 @@ // ***** State Updaters ***** // Override the MIDI note off method to process the release angle - void midiNoteOff(int noteNumber, bool touchIsOn, bool keyMotionActive, + /*void midiNoteOff(int noteNumber, bool touchIsOn, bool keyMotionActive, Node<KeyTouchFrame>* touchBuffer, Node<key_position>* positionBuffer, - KeyPositionTracker* positionTracker); + KeyPositionTracker* positionTracker);*/ + //void midiNoteOffReceived(int channel); + +private: + // ***** Private Methods ***** + void initializeMappingParameters(int noteNumber, TouchkeyReleaseAngleMapping *mapping); + void clearNotes(); + + int currentConfiguration_; // What configuration we're currently in + float windowSizeMilliseconds_; // How long before release to consider touch data + bool upEnabled_, downEnabled_; // Whether messages are enabled for upward and downward releases + float upMinimumAngle_; // Minimum release angle for trigger for up... + float downMinimumAngle_; // ...and down cases + int upNotes_[RELEASE_ANGLE_MAX_SEQUENCE_LENGTH]; // Notes and velocities to send on upward + int upVelocities_[RELEASE_ANGLE_MAX_SEQUENCE_LENGTH]; // and downward release + int downNotes_[RELEASE_ANGLE_MAX_SEQUENCE_LENGTH]; + int downVelocities_[RELEASE_ANGLE_MAX_SEQUENCE_LENGTH]; }; #endif /* defined(__TouchKeys__TouchkeyReleaseAngleMappingFactory__) */
--- a/Source/TouchKeys/PianoKey.cpp Wed Aug 27 13:18:27 2014 +0100 +++ b/Source/TouchKeys/PianoKey.cpp Wed Sep 24 00:29:18 2014 +0100 @@ -413,9 +413,6 @@ // Note Off message from associated MIDI keyboard. Clear all old MIDI state. void PianoKey::midiNoteOff(MidiKeyboardSegment *who, timestamp_type timestamp) { midiNoteIsOn_ = false; - midiVelocity_ = 0; - midiChannel_ = -1; - midiAftertouch_.clear(); midiOffTimestamp_ = timestamp; if(keyboard_.mappingFactory(who) != 0) @@ -424,6 +421,10 @@ keyboard_.sendMessage("/midi/noteoff", "ii", noteNumber_, midiChannel_, LO_ARGS_END); + midiVelocity_ = 0; + midiChannel_ = -1; + midiAftertouch_.clear(); + // Update GUI if it is available if(keyboard_.gui() != 0) { keyboard_.gui()->setMidiActive(noteNumber_, false);
--- a/Source/TouchKeys/PianoKeyboard.cpp Wed Aug 27 13:18:27 2014 +0100 +++ b/Source/TouchKeys/PianoKeyboard.cpp Wed Sep 24 00:29:18 2014 +0100 @@ -26,7 +26,7 @@ #include "PianoKeyboard.h" #include "TouchkeyDevice.h" #include "../Mappings/Mapping.h" -#include "MidiOutputcontroller.h" +#include "MidiOutputController.h" #include "../Mappings/MappingFactory.h" #include "../Mappings/MappingScheduler.h" @@ -311,4 +311,4 @@ delete (*it); mappingScheduler_->stop(); delete mappingScheduler_; -} \ No newline at end of file +}
--- a/TouchKeys.jucer Wed Aug 27 13:18:27 2014 +0100 +++ b/TouchKeys.jucer Wed Sep 24 00:29:18 2014 +0100 @@ -56,6 +56,10 @@ resource="0" file="Source/Mappings/Vibrato/TouchkeyVibratoMappingFactory.h"/> </GROUP> <GROUP id="{E8E7436B-8FBA-DCC3-A9A3-B7FA7AF31483}" name="ReleaseAngle"> + <FILE id="kQ9zEZ" name="TouchkeyReleaseAngleMappingExtendedEditor.cpp" + compile="1" resource="0" file="Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingExtendedEditor.cpp"/> + <FILE id="vyYFkY" name="TouchkeyReleaseAngleMappingExtendedEditor.h" + compile="0" resource="0" file="Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMappingExtendedEditor.h"/> <FILE id="JOJw40" name="TouchkeyReleaseAngleMapping.cpp" compile="1" resource="0" file="Source/Mappings/ReleaseAngle/TouchkeyReleaseAngleMapping.cpp"/> <FILE id="Au4RmN" name="TouchkeyReleaseAngleMapping.h" compile="0" @@ -275,7 +279,7 @@ extraLinkerFlags="/usr/local/lib/liblo.a" smallIcon="mbX6Jp" bigIcon="b3DhPc"> <CONFIGURATIONS> - <CONFIGURATION name="Debug" osxSDK="default" osxCompatibility="default" osxArchitecture="64BitIntel" + <CONFIGURATION name="Debug" osxSDK="default" osxCompatibility="10.6 SDK" osxArchitecture="64BitIntel" isDebug="1" optimisation="1" targetName="TouchKeys" headerPath="/usr/local/include"/> <CONFIGURATION name="Release" osxSDK="default" osxCompatibility="10.6 SDK" osxArchitecture="64BitUniversal" isDebug="0" optimisation="2" targetName="TouchKeys" headerPath="/usr/local/include"/>