diff --git a/Source/LumatoneEditorState.h b/Source/LumatoneEditorState.h index e017330..8a1a6a8 100644 --- a/Source/LumatoneEditorState.h +++ b/Source/LumatoneEditorState.h @@ -31,9 +31,6 @@ namespace LumatoneEditorProperty static const juce::Identifier InCalibrationMode = juce::Identifier("InCalibrationMode"); static const juce::Identifier FirmwareUpdatePerformed = juce::Identifier("FirmwareUpdatePerformed"); - static const juce::Identifier InactiveMacroButtonColour = juce::Identifier("InactiveMacroButtonColour"); - static const juce::Identifier ActiveMacroButtonColour = juce::Identifier("ActiveMacroButtonColour"); - static const juce::Identifier ColourPalettes = juce::Identifier("ColourPalettes"); static const juce::Identifier CurrentFile = juce::Identifier("CurrentFile"); diff --git a/Source/Main.cpp b/Source/Main.cpp index 3809a4c..9e79331 100644 --- a/Source/Main.cpp +++ b/Source/Main.cpp @@ -720,6 +720,28 @@ bool TerpstraSysExApplication::aboutTerpstraSysEx() return true; } +//void LumatoneController::loadRandomMapping(int testTimeoutMs, int maxIterations, int i) +//{ +// auto dir = juce::File::getSpecialLocation(juce::File::SpecialLocationType::userDocumentsDirectory).getChildFile("Lumatone Editor").getChildFile("Mappings"); +// auto mappings = dir.findChildFiles(juce::File::TypesOfFileToFind::findFiles, true); +// auto numfiles = mappings.size(); +// auto r = juce::Random(); +// +// auto fileIndex = r.nextInt(numfiles-1); +// auto file = mappings[fileIndex]; +// +// if (file.exists() && file.hasFileExtension(".ltn")) +// { +// DBG("Found " + juce::String(numfiles) + " files, loading " + file.getFileName()); +// juce::MessageManager::callAsync([file]() { TerpstraSysExApplication::getApp().setCurrentFile(file); }); +// } +// +//// if (i < maxIterations) +//// Timer::callAfterDelay(testTimeoutMs, [&]() { loadRandomMapping(testTimeoutMs, maxIterations, i + 1); }); +//// else +//// DBG("Finished random mappings test."); +//} + //============================================================================== // This macro generates the main() routine that launches the app. START_JUCE_APPLICATION(TerpstraSysExApplication) diff --git a/Source/lumatone_editor_library/data/application_state.cpp b/Source/lumatone_editor_library/data/application_state.cpp index 1b642c9..14fd2dc 100644 --- a/Source/lumatone_editor_library/data/application_state.cpp +++ b/Source/lumatone_editor_library/data/application_state.cpp @@ -134,6 +134,30 @@ bool LumatoneApplicationState::performLumatoneAction(LumatoneAction *action, boo return action->perform(); } +void LumatoneApplicationState::setInactiveMacroButtonColour(juce::Colour buttonColour) +{ + LumatoneState::setInactiveMacroButtonColour(buttonColour); + + if (doSendChangesToDevice()) + { + controller->sendMacroButtonInactiveColour(buttonColour.toString()); + } + + editorListeners->call(&LumatoneEditor::EditorListener::macroButtonInactiveColourChanged, buttonColour); +} + +void LumatoneApplicationState::setActiveMacroButtonColour(juce::Colour buttonColour) +{ + LumatoneState::setInactiveMacroButtonColour(buttonColour); + + if (doSendChangesToDevice()) + { + controller->sendMacroButtonInactiveColour(buttonColour.toString()); + } + + editorListeners->call(&LumatoneEditor::EditorListener::macroButtonActiveColourChanged, buttonColour); +} + juce::ValueTree LumatoneApplicationState::loadStateProperties(juce::ValueTree stateIn) { juce::ValueTree newState = (stateIn.hasType(LumatoneStateProperty::StateTree)) @@ -468,9 +492,20 @@ bool LumatoneApplicationState::Controller::requestCompleteConfigFromDevice() if (appState.connectionState != ConnectionState::ONLINE) return false; - // Request MIDI channel, MIDI note, colour and key type config for all keys - appState.controller->sendGetCompleteMappingRequest(); + requestSettingsFromDevice(); + requestMappingFromDevice(); + + return true; +} + +bool LumatoneApplicationState::Controller::requestSettingsFromDevice() +{ + if (appState.connectionState != ConnectionState::ONLINE) + return false; + // Macro button colours + appState.controller->requestMacroButtonColours(); + // General options appState.controller->requestPresetFlags(); appState.controller->requestExpressionPedalSensitivity(); @@ -489,10 +524,21 @@ bool LumatoneApplicationState::Controller::requestMappingFromDevice() if (appState.connectionState != ConnectionState::ONLINE) return false; + // Request MIDI channel, MIDI note, colour and key type config for all keys appState.controller->sendGetCompleteMappingRequest(); return true; } +void LumatoneApplicationState::Controller::setInactiveMacroButtonColour(juce::Colour buttonColour) +{ + appState.setInactiveMacroButtonColour(buttonColour); +} + +void LumatoneApplicationState::Controller::setActiveMacroButtonColour(juce::Colour buttonColour) +{ + appState.setActiveMacroButtonColour(buttonColour); +} + void LumatoneApplicationState::DeviceController::setConnectionState(ConnectionState newState, bool sendNotification) { deviceAppState.connectionState = newState; diff --git a/Source/lumatone_editor_library/data/application_state.h b/Source/lumatone_editor_library/data/application_state.h index 5822079..31f4e9f 100644 --- a/Source/lumatone_editor_library/data/application_state.h +++ b/Source/lumatone_editor_library/data/application_state.h @@ -99,14 +99,14 @@ class LumatoneApplicationState : public LumatoneState virtual void setConfigTable(LumatoneConfigTable::TableType type, const LumatoneConfigTable& table) override; - //void setVelocityIntervalTable(const LumatoneConfigTable& table) override; - //void setNoteVelocityTable(const LumatoneConfigTable& tableIn) override; - //void setAftertouchTable(const LumatoneConfigTable& tableIn) override; - //void setLumatouchTable(const LumatoneConfigTable& tableIn) override; - private: bool performLumatoneAction(LumatoneAction* action, bool undoable = true, bool newTransaction = true); + +protected: + virtual void setInactiveMacroButtonColour(juce::Colour buttonColour) override; + virtual void setActiveMacroButtonColour(juce::Colour buttonColour) override; + protected: virtual juce::ValueTree loadStateProperties(juce::ValueTree stateIn); @@ -158,8 +158,12 @@ class LumatoneApplicationState : public LumatoneState Controller(LumatoneApplicationState& stateIn) : appState(stateIn) {} - virtual bool requestCompleteConfigFromDevice(); + virtual bool requestSettingsFromDevice(); virtual bool requestMappingFromDevice(); + virtual bool requestCompleteConfigFromDevice(); + + void setInactiveMacroButtonColour(juce::Colour buttonColour); + void setActiveMacroButtonColour(juce::Colour buttonColour); virtual bool performAction(LumatoneAction* action, bool undoable=true, bool newTransaction=true); diff --git a/Source/lumatone_editor_library/data/lumatone_state.cpp b/Source/lumatone_editor_library/data/lumatone_state.cpp index d140e75..25ffbdd 100644 --- a/Source/lumatone_editor_library/data/lumatone_state.cpp +++ b/Source/lumatone_editor_library/data/lumatone_state.cpp @@ -19,6 +19,16 @@ juce::Array LumatoneState::getLumatoneStateProperties() properties.add(LumatoneStateProperty::LastConnectedFirmwareVersion); properties.add(LumatoneStateProperty::LastConnectedNumBoards); + properties.add(LumatoneStateProperty::LightsOnAfterKeystroke); + properties.add(LumatoneStateProperty::AftertouchEnabled); + properties.add(LumatoneStateProperty::InvertExpression); + properties.add(LumatoneStateProperty::InvertSustain); + + properties.add(LumatoneStateProperty::ExpressionSensitivity); + + properties.add(LumatoneStateProperty::InactiveMacroButtonColour); + properties.add(LumatoneStateProperty::ActiveMacroButtonColour); + properties.add(LumatoneStateProperty::MappingData); return properties; @@ -46,6 +56,8 @@ LumatoneState::LumatoneState(juce::String nameIn, const LumatoneState& stateToCo midiKeyMap = stateToCopy.midiKeyMap; } +LumatoneState::LumatoneState(const LumatoneState &stateIn) : LumatoneState(stateIn.name + "Copy", stateIn) {} + LumatoneState::~LumatoneState() { state.removeListener(this); @@ -82,20 +94,15 @@ void LumatoneState::handleStatePropertyChange(juce::ValueTree stateIn, const juc ); firmwareVersion = LumatoneFirmware::Version::fromReleaseVersion(determinedVersion); } - else if (property == LumatoneStateProperty::MappingData) + else if (property == LumatoneStateProperty::InactiveMacroButtonColour) + { + auto readColour = juce::Colour::fromString(stateIn[property].toString()); + inactiveMacroButtonColour = readColour; + } + else if (property == LumatoneStateProperty::ActiveMacroButtonColour) { - // juce::String mappingString = stateIn.getProperty(property).toString(); - // if (mappingString.isEmpty()) - // return; - - // auto stringArray = juce::StringArray::fromLines(mappingString); - // LumatoneLayout loadedLayout(getNumBoards(), getOctaveBoardSize()); - // loadedLayout.fromStringArray(stringArray); - - // if (!loadedLayout.isEmpty()) - // { - // mappingData.reset(new LumatoneLayout(loadedLayout)); - // } + auto readColour = juce::Colour::fromString(stateIn[property].toString()); + activeMacroButtonColour = readColour; } } @@ -127,11 +134,7 @@ void LumatoneState::setLumatoneVersion(LumatoneFirmware::ReleaseVersion versionI if (writeToState) { - state.setPropertyExcludingListener( - this, - LumatoneStateProperty::LastConnectedFirmwareVersion, - (int)determinedVersion, - undoManager); + setStateProperty(LumatoneStateProperty::LastConnectedFirmwareVersion, (int)determinedVersion); } } @@ -273,63 +276,14 @@ void LumatoneState::setConfigTable(LumatoneConfigTable::TableType type, const Lu mappingData->setConfigTable(type, table.velocityValues); } -// bool LumatoneState::loadLayoutFromFile(const juce::File& layoutFile) -// { -// bool fileOpened = false; -// bool fileParsed = false; - -// if (layoutFile.existsAsFile()) -// { -// fileOpened = true; - -// juce::StringArray stringArray; -// layoutFile.readLines(stringArray); - -// LumatoneLayout newLayout(getNumBoards(), getOctaveBoardSize(), true); -// newLayout.fromStringArray(stringArray); - -// // TODO: something if boards/size don't match? -// fileParsed = true; - - -// if (fileParsed) -// { -// *mappingData = LumatoneLayout(newLayout); - -// auto layoutString = mappingData->toStringArray().joinIntoString(juce::newLine); -// DBG("Loaded: " + layoutString); - -// writeStringProperty(LumatoneStateProperty::MappingData, layoutString, undoManager); - -// invertSustain = mappingData->invertSustain; -// writeBoolProperty(LumatoneStateProperty::InvertSustain, invertSustain, undoManager); - -// invertExpression = mappingData->invertExpression; -// writeBoolProperty(LumatoneStateProperty::InvertExpression, invertExpression, undoManager); - -// expressionSensitivity = mappingData->expressionSensitivity; -// writeIntProperty(LumatoneStateProperty::ExpressionSensitivity, expressionSensitivity, undoManager); - -// // Mark file as unchanged -// //setHasChangesToSave(false); - -// // Clear undo history -// //undoManager.clearUndoHistory(); - -// // Add file to recent files list -// //recentFiles.addFile(currentFile); - -// return true; -// } -// } - -// if (fileOpened) -// { -// // Show error message -// juce::AlertWindow::showMessageBoxAsync(juce::AlertWindow::AlertIconType::WarningIcon, "Open File Error", "The file " + layoutFile.getFullPathName() + " could not be opened."); - -// // XXX Update Window title in any case? Make file name empty/make data empty in case of error? -// } +void LumatoneState::setInactiveMacroButtonColour(juce::Colour buttonColour) +{ + inactiveMacroButtonColour = buttonColour; + setStateProperty(LumatoneStateProperty::InactiveMacroButtonColour, buttonColour.toString()); +} -// return false; -// } +void LumatoneState::setActiveMacroButtonColour(juce::Colour buttonColour) +{ + activeMacroButtonColour = buttonColour; + setStateProperty(LumatoneStateProperty::InactiveMacroButtonColour, buttonColour.toString()); +} diff --git a/Source/lumatone_editor_library/data/lumatone_state.h b/Source/lumatone_editor_library/data/lumatone_state.h index 7fd32bc..d88b25b 100644 --- a/Source/lumatone_editor_library/data/lumatone_state.h +++ b/Source/lumatone_editor_library/data/lumatone_state.h @@ -30,9 +30,14 @@ namespace LumatoneStateProperty static const juce::Identifier MappingData = juce::Identifier("MappingData"); + static const juce::Identifier LightsOnAfterKeystroke = juce::Identifier("LightsOnAfterKeystroke"); + static const juce::Identifier AftertouchEnabled = juce::Identifier("AftertouchEnabled"); static const juce::Identifier InvertExpression = juce::Identifier("InvertExpression"); static const juce::Identifier InvertSustain = juce::Identifier("InvertSustain"); static const juce::Identifier ExpressionSensitivity = juce::Identifier("ExpressionSensitivity"); + + static const juce::Identifier InactiveMacroButtonColour = juce::Identifier("InactiveMacroButtonColour"); + static const juce::Identifier ActiveMacroButtonColour = juce::Identifier("ActiveMacroButtonColour"); }; class LumatoneState : public LumatoneStateBase @@ -41,6 +46,7 @@ class LumatoneState : public LumatoneStateBase LumatoneState(juce::String nameIn, juce::ValueTree stateIn=juce::ValueTree(), juce::UndoManager* undoManager=nullptr); LumatoneState(juce::String nameIn, const LumatoneState& stateToCopy); + LumatoneState(const LumatoneState& stateIn); virtual ~LumatoneState() override; @@ -82,6 +88,9 @@ class LumatoneState : public LumatoneStateBase virtual void setConfigTable(LumatoneConfigTable::TableType type, const LumatoneConfigTable& table); + virtual void setInactiveMacroButtonColour(juce::Colour buttonColour); + virtual void setActiveMacroButtonColour(juce::Colour buttonColour); + public: // Layout Helpers int getNumBoards() const { return mappingData->getNumBoards(); } @@ -93,6 +102,9 @@ class LumatoneState : public LumatoneStateBase bool getInvertSustain() const { return mappingData->getInvertSustain(); } int getExpressionSensitivity() const { return mappingData->getExpressionSensitivity(); } + juce::Colour getInactiveMacroButtonColour() const { return inactiveMacroButtonColour; } + juce::Colour getActiveMacroButtonColour() const { return activeMacroButtonColour; } + protected: void setConnectedSerialNumber(juce::String serialNumberIn); void setFirmwareVersion(LumatoneFirmware::Version& versionIn, bool writeToState=false); @@ -119,15 +131,17 @@ class LumatoneState : public LumatoneStateBase std::shared_ptr mappingData; std::shared_ptr midiKeyMap; - private: juce::String connectedSerialNumber = juce::String(); LumatoneFirmware::ReleaseVersion determinedVersion; LumatoneFirmware::Version firmwareVersion; LumatoneFirmware::Version incomingVersion; + + juce::Colour inactiveMacroButtonColour; + juce::Colour activeMacroButtonColour; }; -#endif LUMATONE_STATE_H +#endif // LUMATONE_STATE_H