From aeea5b8e97fa22a7461032f8ae37ee2f7a13d3fc Mon Sep 17 00:00:00 2001 From: joyo Date: Mon, 26 Feb 2024 19:55:11 -0800 Subject: [PATCH] More smarts more grid --- private/plugin.json | 33 + private/res/FaderBank.svg | 979 +++++++++++++++++++++++ private/res/GridJnctLPP3.svg | 972 ++++++++++++++++++++++ private/src/Color.cpp | 13 + private/src/FaderBank.cpp | 3 + private/src/FaderBank.hpp | 163 ++++ private/src/GridJnct.cpp | 4 + private/src/GridJnct.hpp | 349 +++++++- private/src/LedDisplayCenterChoiceEx.hpp | 40 + private/src/MidiWidget.hpp | 189 +++++ private/src/SmartGrid.cpp | 55 +- private/src/SmartGrid.hpp | 123 ++- private/src/TheNonagon.hpp | 3 +- private/src/plugin.cpp | 3 + private/src/plugin.hpp | 3 + 15 files changed, 2842 insertions(+), 90 deletions(-) create mode 100644 private/res/FaderBank.svg create mode 100644 private/res/GridJnctLPP3.svg create mode 100644 private/src/Color.cpp create mode 100644 private/src/FaderBank.cpp create mode 100644 private/src/FaderBank.hpp create mode 100644 private/src/GridJnct.cpp create mode 100644 private/src/LedDisplayCenterChoiceEx.hpp create mode 100644 private/src/MidiWidget.hpp diff --git a/private/plugin.json b/private/plugin.json index 2cae4b3..883a497 100644 --- a/private/plugin.json +++ b/private/plugin.json @@ -96,6 +96,39 @@ [ ] }, + { + "slug": "GridJnctLPP3", + "name": "GridJnctLPP3", + "description": "GridJnctLPP3", + "tags": + [ + ], + "keywords": + [ + ] + }, + { + "slug": "GridCnct", + "name": "GridCnct", + "description": "GridCnct", + "tags": + [ + ], + "keywords": + [ + ] + }, + { + "slug": "FaderBank", + "name": "FaderBank", + "description": "FaderBank", + "tags": + [ + ], + "keywords": + [ + ] + }, { "slug": "PhasorEnvelope", "name": "PhasorEnvelope", diff --git a/private/res/FaderBank.svg b/private/res/FaderBank.svg new file mode 100644 index 0000000..725e37c --- /dev/null +++ b/private/res/FaderBank.svg @@ -0,0 +1,979 @@ + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/private/res/GridJnctLPP3.svg b/private/res/GridJnctLPP3.svg new file mode 100644 index 0000000..5cb58be --- /dev/null +++ b/private/res/GridJnctLPP3.svg @@ -0,0 +1,972 @@ + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/private/src/Color.cpp b/private/src/Color.cpp new file mode 100644 index 0000000..2b6968c --- /dev/null +++ b/private/src/Color.cpp @@ -0,0 +1,13 @@ +#include "SmartGrid.hpp" + +namespace SmartGrid +{ +uint8_t Color::ToLPVelocity() +{ + static constexpr uint8_t velocities[] = {0, 0, 47, 47, 51, 51, 46, 46, 46, 46, 46, 46, 69, 69, 69, 67, 0, 35, 39, 39, 51, 46, 46, 46, 46, 46, 46, 46, 69, 69, 69, 67, 27, 35, 39, 39, 51, 42, 42, 42, 42, 42, 42, 69, 69, 69, 69, 67, 27, 31, 31, 31, 112, 42, 42, 42, 42, 42, 42, 69, 69, 69, 69, 67, 64, 64, 64, 64, 65, 68, 38, 42, 42, 66, 66, 69, 69, 69, 67, 67, 123, 123, 123, 123, 65, 68, 38, 38, 38, 66, 66, 66, 69, 69, 79, 79, 26, 26, 30, 30, 65, 102, 68, 38, 66, 66, 66, 66, 66, 92, 41, 41, 26, 26, 30, 30, 34, 34, 68, 66, 66, 66, 66, 66, 41, 41, 41, 41, 26, 26, 76, 30, 34, 34, 68, 66, 66, 66, 66, 66, 41, 41, 41, 41, 76, 76, 76, 76, 76, 34, 68, 66, 66, 66, 66, 66, 41, 41, 41, 41, 76, 76, 76, 76, 76, 76, 68, 66, 66, 66, 66, 66, 78, 78, 78, 78, 76, 76, 76, 122, 122, 122, 29, 29, 66, 66, 33, 33, 78, 78, 78, 78, 122, 122, 122, 122, 122, 122, 29, 29, 77, 77, 33, 33, 78, 78, 78, 78, 122, 122, 122, 122, 122, 122, 29, 29, 77, 77, 33, 33, 90, 90, 78, 78, 122, 122, 122, 122, 122, 29, 29, 29, 77, 77, 33, 33, 90, 90, 90, 78, 88, 88, 88, 88, 88, 29, 29, 29, 77, 77, 33, 33, 90, 90, 90, 90, 0, 0, 47, 51, 51, 51, 46, 50, 50, 50, 50, 50, 69, 69, 69, 69, 0, 35, 39, 103, 51, 51, 46, 50, 50, 50, 50, 50, 69, 69, 69, 69, 15, 35, 39, 103, 103, 103, 104, 50, 50, 50, 50, 69, 69, 69, 69, 69, 19, 19, 1, 103, 112, 104, 104, 104, 104, 104, 104, 69, 69, 69, 69, 69, 19, 64, 101, 103, 112, 104, 104, 104, 104, 66, 66, 69, 69, 69, 69, 67, 123, 101, 101, 101, 65, 68, 38, 38, 38, 66, 66, 66, 69, 69, 69, 79, 101, 101, 101, 101, 65, 102, 68, 38, 66, 66, 66, 66, 92, 92, 92, 41, 101, 101, 30, 30, 34, 34, 68, 66, 66, 66, 66, 66, 92, 92, 41, 41, 101, 101, 76, 76, 34, 34, 68, 66, 66, 66, 66, 66, 92, 92, 41, 41, 76, 76, 76, 76, 76, 76, 68, 66, 66, 66, 66, 66, 92, 92, 41, 41, 76, 76, 76, 76, 76, 76, 76, 66, 66, 66, 66, 66, 92, 92, 78, 78, 76, 76, 76, 122, 122, 122, 29, 29, 66, 66, 33, 33, 78, 78, 78, 78, 122, 122, 122, 122, 122, 122, 29, 29, 77, 77, 33, 33, 78, 78, 78, 78, 122, 122, 122, 122, 122, 122, 29, 29, 77, 77, 33, 33, 90, 90, 78, 78, 122, 122, 122, 122, 88, 29, 29, 29, 77, 77, 33, 33, 90, 90, 90, 78, 88, 88, 88, 88, 88, 29, 29, 29, 77, 77, 33, 33, 90, 90, 90, 90, 7, 59, 55, 55, 51, 51, 50, 50, 50, 50, 50, 50, 69, 69, 69, 80, 7, 15, 55, 103, 112, 112, 50, 50, 50, 50, 50, 50, 69, 69, 69, 80, 15, 15, 1, 103, 112, 112, 50, 50, 50, 50, 50, 50, 69, 69, 69, 80, 19, 19, 1, 71, 112, 112, 104, 104, 104, 104, 104, 69, 69, 69, 69, 80, 19, 19, 1, 71, 112, 112, 104, 104, 104, 66, 66, 69, 69, 69, 69, 80, 19, 18, 18, 71, 112, 117, 38, 38, 38, 66, 66, 92, 92, 92, 92, 79, 18, 18, 18, 18, 65, 102, 68, 38, 66, 66, 66, 92, 92, 92, 92, 92, 18, 18, 18, 18, 34, 34, 68, 66, 66, 66, 66, 92, 92, 92, 92, 41, 18, 18, 18, 18, 34, 34, 68, 66, 66, 66, 66, 92, 92, 92, 92, 41, 18, 18, 76, 76, 76, 76, 68, 66, 66, 66, 66, 92, 92, 92, 92, 40, 76, 76, 76, 76, 76, 76, 76, 66, 66, 66, 66, 92, 92, 92, 40, 40, 76, 76, 76, 122, 122, 122, 29, 24, 66, 66, 33, 92, 92, 92, 78, 78, 122, 122, 122, 122, 122, 122, 29, 24, 77, 77, 33, 33, 32, 78, 78, 78, 122, 122, 122, 122, 122, 122, 29, 24, 77, 77, 33, 33, 32, 90, 36, 36, 122, 122, 122, 122, 88, 20, 29, 24, 77, 77, 33, 33, 32, 90, 90, 36, 88, 88, 88, 88, 88, 20, 29, 24, 77, 77, 33, 33, 32, 90, 90, 90, 7, 59, 55, 55, 51, 51, 50, 50, 50, 50, 50, 50, 69, 69, 80, 80, 11, 59, 55, 71, 112, 112, 50, 50, 50, 50, 50, 50, 69, 69, 80, 80, 11, 11, 1, 71, 112, 112, 112, 50, 50, 50, 50, 50, 69, 69, 80, 80, 11, 11, 71, 71, 112, 112, 104, 104, 104, 104, 104, 69, 69, 69, 80, 80, 11, 125, 71, 71, 112, 117, 104, 104, 104, 66, 92, 92, 92, 92, 80, 80, 11, 18, 71, 71, 117, 117, 117, 38, 38, 66, 92, 92, 92, 92, 92, 80, 18, 18, 18, 18, 65, 117, 68, 38, 66, 66, 92, 92, 92, 92, 92, 92, 18, 18, 18, 18, 34, 117, 68, 66, 66, 66, 92, 92, 92, 92, 92, 44, 18, 18, 63, 63, 34, 117, 68, 66, 66, 66, 92, 92, 92, 92, 92, 44, 18, 18, 76, 76, 76, 117, 68, 118, 118, 66, 92, 92, 92, 92, 92, 40, 76, 76, 76, 76, 76, 76, 24, 24, 118, 66, 92, 92, 92, 92, 40, 40, 76, 76, 76, 122, 122, 20, 24, 24, 28, 28, 28, 32, 32, 92, 40, 40, 122, 122, 122, 122, 122, 20, 24, 24, 28, 28, 28, 32, 32, 36, 36, 36, 122, 122, 122, 122, 122, 20, 24, 24, 28, 28, 28, 32, 32, 36, 36, 36, 122, 122, 122, 122, 17, 20, 24, 24, 28, 28, 28, 32, 32, 32, 36, 36, 17, 17, 17, 17, 17, 20, 24, 24, 28, 28, 28, 32, 32, 32, 32, 36, 121, 121, 55, 55, 51, 51, 54, 50, 50, 50, 50, 50, 69, 69, 80, 80, 121, 121, 55, 71, 112, 112, 54, 50, 50, 50, 50, 50, 69, 69, 80, 80, 11, 11, 1, 71, 112, 112, 54, 50, 50, 50, 50, 50, 69, 69, 80, 80, 100, 100, 71, 71, 112, 117, 104, 104, 104, 104, 104, 69, 69, 69, 80, 80, 125, 125, 125, 71, 117, 117, 117, 117, 117, 117, 80, 80, 80, 80, 80, 80, 125, 125, 125, 117, 117, 117, 117, 117, 117, 117, 92, 92, 92, 92, 80, 80, 125, 63, 63, 63, 117, 117, 117, 117, 117, 66, 92, 92, 92, 92, 92, 44, 63, 63, 63, 63, 63, 117, 117, 117, 66, 66, 92, 92, 92, 92, 44, 44, 63, 63, 63, 63, 63, 117, 117, 117, 118, 118, 92, 92, 92, 92, 44, 44, 63, 63, 63, 63, 63, 117, 117, 118, 118, 70, 70, 92, 92, 92, 40, 40, 63, 63, 63, 63, 63, 20, 24, 24, 118, 28, 28, 40, 40, 40, 40, 40, 63, 63, 111, 111, 111, 20, 24, 24, 28, 28, 28, 32, 32, 40, 40, 40, 111, 111, 111, 111, 111, 20, 24, 24, 28, 28, 28, 32, 32, 36, 36, 36, 122, 122, 122, 122, 17, 20, 24, 24, 28, 28, 28, 32, 32, 36, 36, 36, 17, 17, 17, 17, 17, 20, 24, 24, 28, 28, 28, 32, 32, 32, 36, 36, 17, 17, 17, 17, 17, 20, 24, 24, 28, 28, 28, 32, 32, 32, 32, 36, 121, 121, 121, 58, 58, 54, 54, 54, 54, 54, 54, 54, 49, 49, 49, 49, 121, 127, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 49, 49, 49, 49, 83, 83, 83, 71, 112, 117, 54, 54, 54, 54, 54, 54, 49, 49, 49, 49, 83, 83, 83, 71, 117, 117, 117, 54, 54, 54, 54, 49, 49, 49, 49, 49, 125, 125, 125, 125, 117, 117, 117, 117, 117, 117, 117, 49, 49, 49, 49, 49, 125, 125, 125, 117, 117, 117, 117, 117, 117, 117, 117, 92, 92, 92, 44, 44, 63, 63, 63, 63, 117, 117, 117, 117, 117, 117, 92, 92, 92, 92, 44, 44, 63, 63, 63, 63, 63, 117, 117, 117, 117, 118, 92, 92, 92, 92, 44, 44, 63, 63, 63, 63, 63, 117, 117, 117, 118, 118, 118, 92, 92, 92, 44, 44, 63, 63, 63, 63, 63, 117, 117, 118, 118, 70, 70, 40, 40, 40, 40, 40, 63, 63, 63, 63, 63, 117, 117, 118, 118, 70, 70, 40, 40, 40, 40, 40, 63, 63, 111, 111, 111, 20, 24, 24, 89, 28, 28, 40, 40, 40, 40, 40, 111, 111, 111, 111, 111, 20, 24, 24, 89, 28, 28, 32, 32, 36, 36, 36, 111, 111, 111, 17, 17, 20, 24, 24, 89, 28, 28, 32, 32, 36, 36, 36, 17, 17, 17, 17, 17, 20, 24, 24, 89, 28, 28, 32, 32, 32, 36, 36, 17, 17, 17, 17, 17, 20, 24, 24, 89, 28, 28, 32, 32, 32, 32, 36, 6, 6, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 49, 49, 49, 49, 127, 127, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 49, 49, 49, 49, 127, 127, 127, 58, 58, 54, 54, 54, 54, 54, 54, 54, 49, 49, 49, 49, 83, 83, 83, 58, 117, 117, 54, 54, 54, 54, 54, 49, 49, 49, 49, 49, 125, 125, 125, 105, 117, 117, 117, 54, 54, 54, 49, 49, 49, 49, 49, 49, 125, 14, 105, 105, 117, 117, 117, 117, 117, 117, 117, 49, 49, 49, 49, 49, 14, 14, 14, 14, 117, 117, 117, 117, 117, 118, 118, 92, 92, 92, 44, 44, 14, 14, 63, 63, 63, 117, 117, 117, 118, 118, 118, 92, 92, 92, 44, 44, 63, 63, 63, 63, 63, 117, 117, 118, 118, 118, 118, 118, 91, 91, 91, 91, 63, 63, 63, 63, 63, 117, 118, 118, 118, 70, 70, 70, 91, 91, 91, 91, 63, 63, 111, 111, 111, 111, 111, 118, 118, 70, 70, 91, 91, 91, 91, 91, 111, 111, 111, 111, 111, 111, 111, 89, 89, 70, 70, 91, 91, 91, 91, 91, 111, 111, 111, 111, 111, 111, 111, 89, 89, 89, 28, 32, 32, 91, 91, 91, 111, 111, 111, 111, 75, 20, 24, 89, 89, 89, 28, 32, 32, 36, 36, 36, 75, 75, 75, 75, 75, 20, 24, 89, 89, 89, 28, 32, 32, 114, 36, 36, 75, 75, 75, 75, 75, 20, 24, 89, 89, 89, 28, 32, 32, 114, 114, 36, 6, 6, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 49, 49, 49, 6, 6, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 49, 49, 49, 10, 10, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 54, 49, 49, 49, 10, 10, 10, 58, 58, 54, 54, 54, 54, 54, 54, 54, 49, 49, 49, 49, 10, 10, 105, 105, 105, 117, 54, 54, 54, 54, 54, 81, 81, 81, 81, 81, 10, 14, 105, 105, 105, 117, 117, 54, 54, 118, 118, 81, 81, 81, 81, 81, 14, 14, 14, 14, 14, 117, 117, 117, 118, 118, 118, 118, 92, 92, 44, 44, 14, 14, 14, 14, 14, 117, 117, 118, 118, 118, 118, 118, 92, 92, 44, 44, 14, 14, 14, 14, 14, 117, 118, 118, 118, 118, 118, 118, 118, 93, 93, 116, 14, 14, 14, 111, 111, 111, 118, 118, 118, 70, 70, 70, 70, 93, 93, 93, 111, 111, 111, 111, 111, 111, 111, 118, 118, 70, 70, 70, 91, 91, 91, 91, 111, 111, 111, 111, 111, 111, 111, 111, 118, 70, 70, 70, 91, 91, 91, 91, 111, 111, 111, 111, 111, 111, 111, 111, 89, 70, 70, 114, 114, 114, 91, 91, 111, 111, 111, 111, 111, 111, 111, 89, 89, 89, 28, 114, 114, 114, 36, 36, 111, 111, 111, 75, 75, 75, 75, 89, 89, 89, 28, 114, 114, 114, 114, 36, 75, 75, 75, 75, 75, 75, 75, 89, 89, 89, 28, 114, 114, 114, 114, 114, 6, 6, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 81, 81, 81, 81, 6, 6, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 81, 81, 81, 81, 10, 10, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 81, 81, 81, 81, 10, 10, 105, 105, 105, 54, 54, 54, 54, 82, 82, 81, 81, 81, 81, 81, 10, 105, 105, 105, 105, 105, 54, 54, 54, 82, 81, 81, 81, 81, 81, 81, 105, 105, 105, 105, 105, 117, 117, 54, 118, 118, 118, 81, 81, 81, 81, 81, 62, 62, 105, 105, 105, 117, 117, 118, 118, 118, 118, 118, 48, 48, 48, 48, 99, 99, 99, 99, 99, 99, 118, 118, 118, 118, 118, 118, 48, 48, 48, 48, 99, 99, 99, 99, 99, 118, 118, 118, 118, 118, 118, 118, 118, 93, 93, 116, 99, 99, 99, 111, 111, 118, 118, 118, 118, 70, 70, 70, 70, 93, 93, 93, 111, 111, 111, 111, 111, 111, 118, 118, 118, 70, 70, 70, 93, 93, 93, 93, 111, 111, 111, 111, 111, 111, 111, 118, 118, 70, 70, 70, 114, 93, 93, 93, 111, 111, 111, 111, 111, 111, 111, 111, 118, 70, 70, 114, 114, 114, 93, 93, 111, 111, 111, 111, 85, 16, 16, 16, 89, 70, 114, 114, 114, 114, 114, 36, 85, 85, 85, 85, 85, 16, 16, 16, 89, 89, 114, 114, 114, 114, 114, 114, 86, 86, 86, 86, 86, 16, 16, 16, 89, 89, 114, 114, 114, 114, 114, 114, 6, 6, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 81, 81, 81, 81, 6, 120, 58, 58, 58, 54, 54, 54, 54, 54, 54, 54, 81, 81, 81, 81, 10, 10, 58, 58, 58, 54, 54, 54, 54, 82, 82, 82, 81, 81, 81, 81, 10, 10, 105, 105, 105, 54, 54, 54, 82, 82, 82, 82, 81, 81, 81, 81, 61, 61, 105, 105, 105, 105, 54, 54, 82, 82, 82, 81, 81, 81, 81, 81, 62, 62, 105, 105, 105, 117, 117, 118, 118, 70, 70, 70, 81, 81, 81, 81, 62, 62, 62, 62, 62, 62, 62, 118, 118, 70, 70, 70, 48, 48, 48, 48, 99, 99, 99, 99, 99, 99, 118, 118, 118, 70, 70, 70, 48, 48, 48, 48, 99, 99, 99, 99, 99, 118, 118, 118, 118, 70, 70, 70, 70, 93, 93, 116, 99, 99, 99, 99, 99, 70, 70, 70, 70, 70, 70, 70, 93, 93, 93, 93, 99, 99, 99, 111, 111, 70, 70, 70, 70, 70, 70, 70, 93, 93, 93, 93, 111, 111, 111, 111, 111, 16, 70, 70, 70, 70, 70, 70, 93, 93, 93, 93, 111, 111, 111, 111, 85, 16, 16, 70, 70, 70, 70, 70, 114, 114, 93, 93, 85, 85, 85, 85, 85, 16, 16, 16, 70, 70, 70, 114, 114, 114, 114, 93, 85, 85, 85, 85, 85, 16, 16, 16, 16, 70, 114, 114, 114, 114, 114, 114, 85, 85, 85, 85, 98, 16, 16, 16, 16, 114, 114, 114, 114, 114, 114, 114, 120, 120, 58, 58, 58, 54, 54, 54, 54, 82, 82, 82, 82, 81, 81, 81, 120, 120, 120, 58, 58, 54, 54, 54, 54, 82, 82, 82, 82, 81, 81, 81, 120, 120, 120, 120, 120, 54, 54, 54, 82, 82, 82, 82, 82, 81, 81, 81, 61, 61, 61, 61, 61, 61, 82, 82, 82, 82, 82, 82, 82, 81, 81, 81, 61, 61, 61, 61, 61, 61, 82, 82, 82, 82, 82, 82, 81, 81, 81, 81, 61, 61, 61, 105, 105, 117, 117, 82, 82, 82, 82, 82, 48, 48, 48, 48, 62, 62, 62, 62, 62, 62, 62, 118, 118, 70, 70, 70, 48, 48, 48, 48, 99, 99, 99, 99, 99, 99, 99, 118, 118, 70, 70, 70, 48, 48, 48, 48, 99, 99, 99, 99, 99, 99, 118, 118, 118, 70, 70, 70, 116, 116, 116, 116, 99, 99, 99, 99, 99, 70, 70, 70, 70, 70, 70, 70, 93, 93, 93, 93, 99, 99, 99, 124, 85, 70, 70, 70, 70, 70, 70, 70, 93, 93, 93, 115, 124, 124, 124, 124, 85, 85, 70, 70, 70, 70, 70, 70, 115, 115, 115, 115, 124, 124, 124, 124, 85, 85, 16, 70, 70, 70, 70, 70, 115, 115, 115, 115, 85, 85, 85, 85, 85, 85, 16, 16, 70, 70, 70, 114, 114, 114, 115, 115, 85, 85, 85, 85, 85, 85, 16, 16, 16, 16, 114, 114, 114, 114, 114, 115, 98, 98, 98, 98, 98, 16, 16, 16, 16, 16, 114, 114, 114, 114, 114, 114, 120, 120, 120, 120, 120, 120, 54, 54, 82, 82, 82, 82, 82, 82, 81, 81, 120, 120, 120, 120, 120, 120, 54, 54, 82, 82, 82, 82, 82, 82, 81, 81, 120, 120, 120, 120, 120, 120, 82, 82, 82, 82, 82, 82, 82, 82, 81, 81, 120, 61, 61, 61, 61, 82, 82, 82, 82, 82, 82, 82, 82, 82, 81, 81, 61, 61, 61, 61, 61, 61, 82, 82, 82, 82, 82, 82, 82, 81, 81, 81, 61, 61, 61, 61, 61, 61, 61, 82, 82, 82, 82, 82, 82, 94, 94, 94, 61, 61, 126, 126, 107, 107, 107, 82, 82, 82, 82, 82, 48, 48, 48, 48, 126, 126, 126, 126, 126, 107, 107, 118, 118, 70, 70, 70, 48, 48, 48, 48, 126, 126, 126, 126, 126, 107, 118, 118, 118, 70, 70, 70, 116, 116, 116, 116, 126, 126, 126, 124, 124, 70, 70, 70, 70, 70, 70, 70, 93, 93, 93, 93, 126, 126, 124, 124, 124, 124, 70, 70, 70, 70, 70, 70, 115, 115, 115, 115, 124, 124, 124, 124, 124, 124, 124, 70, 70, 70, 70, 115, 115, 115, 115, 115, 124, 124, 124, 124, 124, 124, 124, 124, 8, 70, 70, 115, 115, 115, 115, 115, 110, 110, 110, 110, 110, 110, 110, 110, 8, 70, 70, 114, 114, 114, 115, 115, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 114, 114, 114, 114, 114, 115, 74, 74, 74, 74, 74, 16, 16, 16, 113, 113, 114, 114, 114, 114, 114, 119, 106, 106, 106, 106, 106, 106, 82, 82, 82, 82, 82, 82, 82, 82, 94, 94, 106, 106, 106, 106, 106, 106, 82, 82, 82, 82, 82, 82, 82, 82, 94, 94, 106, 106, 106, 106, 106, 106, 82, 82, 82, 82, 82, 82, 82, 82, 94, 94, 106, 106, 106, 106, 106, 82, 82, 82, 82, 82, 82, 82, 82, 82, 94, 94, 61, 61, 61, 61, 61, 82, 82, 82, 82, 82, 82, 82, 82, 94, 94, 94, 61, 61, 126, 126, 107, 107, 82, 82, 82, 82, 82, 82, 82, 94, 94, 94, 126, 126, 126, 126, 107, 107, 107, 82, 82, 82, 82, 82, 82, 94, 94, 94, 126, 126, 126, 126, 126, 107, 107, 107, 82, 82, 82, 82, 48, 48, 48, 48, 126, 126, 126, 126, 126, 107, 107, 118, 118, 70, 70, 70, 116, 116, 116, 116, 126, 126, 126, 124, 124, 124, 70, 70, 70, 70, 70, 70, 93, 93, 93, 93, 126, 126, 124, 124, 124, 124, 124, 70, 70, 70, 70, 70, 115, 115, 115, 115, 124, 124, 124, 124, 124, 124, 124, 124, 8, 70, 70, 115, 115, 115, 115, 115, 124, 124, 124, 124, 124, 124, 124, 124, 8, 8, 8, 8, 115, 115, 115, 115, 124, 124, 124, 124, 74, 74, 74, 113, 8, 8, 8, 114, 114, 114, 115, 115, 74, 74, 74, 74, 74, 74, 74, 113, 113, 113, 113, 114, 114, 114, 119, 119, 74, 74, 74, 74, 73, 73, 73, 113, 113, 113, 113, 114, 114, 114, 119, 119, 106, 106, 106, 106, 106, 57, 57, 82, 82, 82, 82, 82, 82, 94, 94, 94, 106, 106, 106, 106, 106, 57, 57, 82, 82, 82, 82, 82, 82, 94, 94, 94, 106, 106, 106, 106, 106, 57, 57, 82, 82, 82, 82, 82, 82, 94, 94, 94, 106, 106, 60, 60, 57, 57, 57, 82, 82, 82, 82, 82, 82, 94, 94, 94, 61, 61, 61, 61, 107, 107, 57, 82, 82, 82, 82, 82, 94, 94, 94, 94, 61, 61, 126, 126, 107, 107, 107, 82, 82, 82, 82, 82, 94, 94, 94, 94, 126, 126, 126, 126, 107, 107, 107, 107, 82, 82, 56, 56, 94, 94, 94, 94, 126, 126, 126, 126, 107, 107, 107, 107, 56, 56, 56, 56, 56, 52, 52, 52, 108, 108, 108, 108, 108, 107, 107, 107, 118, 56, 56, 56, 116, 116, 116, 116, 108, 108, 108, 124, 124, 107, 107, 70, 70, 70, 70, 70, 93, 93, 93, 93, 124, 124, 124, 124, 124, 124, 124, 8, 8, 70, 70, 70, 115, 115, 115, 115, 124, 124, 124, 124, 124, 124, 124, 8, 8, 8, 8, 8, 115, 115, 115, 115, 124, 124, 124, 124, 124, 124, 124, 8, 8, 8, 8, 8, 8, 115, 115, 115, 124, 124, 124, 124, 73, 73, 73, 113, 8, 8, 8, 8, 114, 119, 119, 119, 74, 74, 74, 74, 73, 73, 73, 113, 113, 113, 113, 113, 114, 119, 119, 119, 73, 73, 73, 73, 73, 73, 73, 113, 113, 113, 113, 113, 114, 119, 119, 119, 106, 106, 106, 106, 57, 57, 57, 95, 82, 82, 82, 82, 82, 94, 94, 94, 106, 106, 106, 106, 57, 57, 57, 95, 82, 82, 82, 82, 82, 94, 94, 94, 106, 72, 72, 72, 57, 57, 57, 95, 82, 82, 82, 82, 82, 94, 94, 94, 60, 60, 60, 60, 57, 57, 57, 95, 82, 82, 82, 82, 82, 94, 94, 94, 60, 60, 60, 60, 107, 107, 57, 95, 82, 82, 82, 82, 94, 94, 94, 94, 84, 84, 108, 107, 107, 107, 107, 95, 82, 82, 56, 56, 94, 94, 94, 94, 84, 84, 108, 107, 107, 107, 107, 107, 56, 56, 56, 56, 56, 94, 94, 94, 108, 108, 108, 108, 107, 107, 107, 107, 56, 56, 56, 56, 56, 52, 52, 52, 108, 108, 108, 108, 108, 107, 107, 107, 56, 56, 56, 56, 56, 52, 52, 52, 108, 108, 108, 108, 108, 107, 107, 107, 8, 56, 56, 56, 56, 52, 52, 52, 108, 108, 108, 124, 124, 107, 107, 8, 8, 8, 56, 56, 56, 115, 115, 115, 124, 124, 124, 124, 124, 124, 8, 8, 8, 8, 8, 8, 8, 115, 115, 115, 124, 124, 124, 124, 124, 124, 8, 8, 8, 8, 8, 8, 8, 119, 119, 119, 124, 124, 124, 124, 109, 109, 113, 113, 8, 8, 8, 8, 8, 119, 119, 119, 109, 109, 109, 109, 109, 109, 113, 113, 113, 113, 113, 113, 119, 119, 119, 119, 73, 73, 73, 73, 73, 12, 113, 113, 113, 113, 113, 113, 119, 119, 119, 119, 72, 72, 72, 72, 57, 57, 57, 95, 95, 95, 95, 95, 53, 53, 53, 53, 72, 72, 72, 72, 57, 57, 57, 95, 95, 95, 95, 95, 53, 53, 53, 53, 72, 72, 72, 72, 57, 57, 57, 95, 95, 95, 95, 95, 53, 53, 53, 53, 60, 60, 60, 60, 57, 57, 57, 95, 95, 82, 82, 82, 53, 53, 53, 53, 60, 60, 60, 60, 107, 107, 57, 95, 95, 82, 56, 56, 53, 53, 53, 53, 84, 84, 84, 84, 107, 107, 4, 95, 56, 56, 56, 56, 53, 53, 53, 53, 84, 84, 84, 84, 107, 107, 4, 4, 56, 56, 56, 56, 56, 52, 52, 52, 9, 9, 9, 9, 107, 107, 4, 4, 56, 56, 56, 56, 56, 52, 52, 52, 108, 108, 108, 108, 107, 107, 4, 4, 56, 56, 56, 56, 56, 52, 52, 52, 96, 96, 96, 96, 96, 107, 4, 4, 8, 56, 56, 56, 56, 52, 52, 52, 96, 96, 96, 96, 96, 107, 4, 8, 8, 8, 56, 56, 56, 52, 52, 52, 96, 96, 96, 124, 124, 8, 8, 8, 8, 8, 8, 8, 8, 52, 52, 52, 124, 124, 124, 124, 109, 8, 8, 8, 8, 8, 8, 8, 8, 8, 119, 119, 109, 109, 109, 109, 109, 109, 8, 8, 8, 8, 8, 8, 8, 119, 119, 119, 109, 109, 109, 109, 109, 109, 109, 113, 8, 8, 8, 8, 119, 119, 119, 119, 13, 13, 13, 13, 13, 12, 113, 113, 113, 113, 113, 113, 119, 119, 119, 119}; + + size_t ix = ((m_red >> 4) << 8) | ((m_green >> 4) << 4) | (m_blue >> 4); + return velocities[ix]; +} + +} diff --git a/private/src/FaderBank.cpp b/private/src/FaderBank.cpp new file mode 100644 index 0000000..befe8d8 --- /dev/null +++ b/private/src/FaderBank.cpp @@ -0,0 +1,3 @@ +#include "FaderBank.hpp" + +Model* modelFaderBank = createModel("FaderBank"); diff --git a/private/src/FaderBank.hpp b/private/src/FaderBank.hpp new file mode 100644 index 0000000..56044ef --- /dev/null +++ b/private/src/FaderBank.hpp @@ -0,0 +1,163 @@ +#pragma once +#include "SmartGrid.hpp" +#include "plugin.hpp" + +namespace SmartGrid +{ + +struct FaderBankSmartGrid : public CompositeGrid +{ + struct BankedFader : public Fader + { + float m_state; + bool m_inputConnected; + bool m_outputConnected; + + BankedFader() + : Fader( + &m_state, + x_gridSize, + ColorScheme::Whites, + 0 /*minValue*/, + 10 /*maxValue*/) + , m_state(0) + , m_inputConnected(false) + , m_outputConnected(false) + { + } + + struct Input + { + bool m_outputConnected; + bool m_inputConnected; + + Input() + : m_outputConnected(false) + , m_inputConnected(false) + { + } + }; + + void ProcessInput(Input& input) + { + m_inputConnected = input.m_inputConnected; + m_outputConnected = input.m_outputConnected; + } + }; + + FaderBankSmartGrid() + : CompositeGrid() + { + for (size_t i = 0; i < x_gridSize; ++i) + { + m_faders[i].reset(new BankedFader()); + AddGrid(i, 0, m_faders[i]); + } + } + + virtual void Apply(Message msg) override + { + if (msg.m_x >= 0 && + msg.m_x < x_gridSize && + m_faders[msg.m_x]->m_outputConnected) + { + CompositeGrid::Apply(msg); + } + } + + virtual Color GetColor(int i, int j) override + { + if (i >= 0 && i < x_gridSize && m_faders[i]->m_outputConnected) + { + return CompositeGrid::GetColor(i, j); + } + + return Color::Off; + } + + + std::shared_ptr m_faders[x_gridSize]; + + struct Input + { + BankedFader::Input m_inputs[x_gridSize]; + }; + + void ProcessInput(Input& input) + { + for (size_t i = 0; i < x_gridSize; ++i) + { + m_faders[i]->ProcessInput(input.m_inputs[i]); + } + } +}; + +struct FaderBank : public Module +{ + FaderBankSmartGrid m_faderBank; + FaderBankSmartGrid::Input m_state; + + static constexpr size_t x_gridIdOutId = x_gridSize; + + FaderBank() + { + config(0, x_gridSize, x_gridSize + 1, 0); + + for (size_t i = 0; i < x_gridSize; ++i) + { + configInput(i, ("Fader " + std::to_string(i)).c_str()); + configOutput(i, ("Fader " + std::to_string(i)).c_str()); + } + + configOutput(x_gridIdOutId, "Grid Id"); + } + + void ReadState() + { + for (size_t i = 0; i < x_gridSize; ++i) + { + m_state.m_inputs[i].m_outputConnected = outputs[i].isConnected(); + m_state.m_inputs[i].m_inputConnected = inputs[i].isConnected(); + } + } + + void SetOutputs() + { + for (size_t i = 0; i < x_gridSize; ++i) + { + outputs[i].setVoltage(m_faderBank.m_faders[i]->m_state); + } + + outputs[x_gridIdOutId].setVoltage(m_faderBank.m_gridId); + } + + void process(const ProcessArgs &args) override + { + m_faderBank.ProcessStatic(args.sampleTime); + ReadState(); + m_faderBank.ProcessInput(m_state); + SetOutputs(); + } +}; + +struct FaderBankWidget : public ModuleWidget +{ + FaderBankWidget(FaderBank* module) + { + setModule(module); + setPanel(createPanel(asset::plugin(pluginInstance, "res/FaderBank.svg"))); + + addOutput(createOutputCentered(Vec(300, 100), module, module->x_gridIdOutId)); + + float rowStart = 50; + + for (size_t i = 0; i < x_gridSize; ++i) + { + float rowPos = 100 + i * 30; + addOutput(createOutputCentered(Vec(rowStart, rowPos), module, i)); + addInput(createInputCentered(Vec(rowStart + 50, rowPos), module, i)); + } + } +}; + +} diff --git a/private/src/GridJnct.cpp b/private/src/GridJnct.cpp new file mode 100644 index 0000000..afa7820 --- /dev/null +++ b/private/src/GridJnct.cpp @@ -0,0 +1,4 @@ +#include "GridJnct.hpp" + +Model* modelGridJnctLPP3 = createModel("GridJnctLPP3"); +Model* modelGridCnct = createModel("GridCnct"); diff --git a/private/src/GridJnct.hpp b/private/src/GridJnct.hpp index b07a752..b932e3a 100644 --- a/private/src/GridJnct.hpp +++ b/private/src/GridJnct.hpp @@ -1,6 +1,7 @@ #pragma once #include "SmartGrid.hpp" #include "PeriodChecker.hpp" +#include "MidiWidget.hpp" namespace SmartGrid { @@ -17,6 +18,19 @@ struct MenuButtonRow Unused = 5 }; + static std::string RowPosToString(RowPos pos) + { + switch (pos) + { + case RowPos::Top: return "Top"; + case RowPos::Right: return "Right"; + case RowPos::Left: return "Left"; + case RowPos::Bottom: return "Bottom"; + case RowPos::SubBottom: return "SubBottom"; + case RowPos::Unused: return ""; + } + } + RowPos m_pos; int m_start; int m_end; @@ -386,6 +400,16 @@ struct MenuGrid : public AbstractGrid { return m_menuButtonRows[static_cast(pos)].m_cells[ix].get(); } + + MenuButton* GetMenuButton(MenuButtonRow::RowPos pos, size_t ix) + { + if (m_menuButtonRows[static_cast(pos)].m_isMenuButton[ix]) + { + return static_cast(Get(pos, ix)); + } + + return nullptr; + } MenuButton* GetSelected() { @@ -503,9 +527,9 @@ struct MenuGridSwitcher : public GridSwitcher virtual ~MenuGridSwitcher() { } - - MenuGridSwitcher(MenuGrid* menu) - : GridSwitcher(menu) + + MenuGridSwitcher() + : GridSwitcher(new MenuGrid()) { } @@ -520,43 +544,286 @@ struct MenuGridSwitcher : public GridSwitcher } }; -// template -// struct GridJnct : Module -// { -// static constexpr size_t GetIOId(MenuButtonRow::RowPos pos, size_t ix) -// { -// return static_cast(pos) + ix; -// } - -// static constexpr size_t GetNumButtonRows() -// { -// switch (Shape) -// { -// case ControllerShape::LaunchpadX: return 2; -// case ControllerShape::LaunchPadPro: return 5; -// } -// } - -// static constexpr size_t GetNumIOIds() -// { -// return GetNumButtonRows() * x_gridSize; -// } - -// static constexpr size_t x_gridIdOutId = GetNumIOIds(); - -// GridJnctInternal m_gridJnct; -// GridJnctInternal::Input m_state; -// PeriodChecker m_periodChecker; - -// void process(const ProcessArgs &args) override -// { -// if (m_periodChecker.Process(args.sampleTime)) -// { -// ReadState(); -// } - -// m_gridJnct.ProcessStatic(m_state); -// } -// }; +template +struct GridJnct : Module +{ + static constexpr size_t GetIOId(MenuButtonRow::RowPos pos, size_t ix) + { + return static_cast(pos) + ix; + } + + static constexpr size_t GetNumButtonRows() + { + return Shape == ControllerShape::LaunchPadX + ? 2 + : Shape == ControllerShape::LaunchPadProMk3 + ? 5 + : 0; + } + + static constexpr size_t GetNumIOIds() + { + return GetNumButtonRows() * x_gridSize; + } + + static constexpr size_t x_numInputs = GetNumIOIds(); + + static constexpr size_t x_gridIdOutId = GetNumIOIds(); + static constexpr size_t x_activeGridIdOutId = x_gridIdOutId + 1; + static constexpr size_t x_numOutputs = x_activeGridIdOutId + 1; + + + MenuGridSwitcher m_switcher; + MenuGrid::Input m_state; + PeriodChecker m_periodChecker; + + GridJnct() + { + config(0, GetNumIOIds(), x_numOutputs, 0); + + for (size_t i = 0; i < GetNumButtonRows(); ++i) + { + m_switcher.GetMenuGrid()->AddMenuRow(static_cast(i)); + } + + for (size_t i = 0; i < GetNumIOIds(); ++i) + { + auto pairPos = m_switcher.GetMenuGrid()->PairPos(i); + configInput(i, (MenuButtonRow::RowPosToString(pairPos.first) + " " + std::to_string(pairPos.second) + " Grid Id ")); + configOutput(i, (MenuButtonRow::RowPosToString(pairPos.first) + " " + std::to_string(pairPos.second) + " Gate ")); + } + + configOutput(x_gridIdOutId, "Grid Id"); + configOutput(x_activeGridIdOutId, "Selected Grid Id"); + } + + void ReadState() + { + for (size_t i = 0; i < GetNumIOIds(); ++i) + { + auto pairPos = m_switcher.GetMenuGrid()->PairPos(i); + size_t posIx = static_cast(pairPos.first); + MenuGrid::MenuButton::Input& input = m_state.m_inputs[posIx][pairPos.second]; + input.m_gateOutConnected = outputs[i].isConnected(); + input.m_hasGrid = inputs[i].isConnected(); + size_t gridId = static_cast(inputs[i].getVoltage() + 0.5); + if (gridId > x_numGridIds) + { + gridId = x_numGridIds; + } + + input.m_gridId = gridId; + } + } + + void SetOutputs() + { + for (size_t i = 0; i < GetNumIOIds(); ++i) + { + auto pairPos = m_switcher.GetMenuGrid()->PairPos(i); + MenuGrid::MenuButton* cell = m_switcher.GetMenuGrid()->GetMenuButton(pairPos.first, pairPos.second); + if (cell) + { + outputs[i].setVoltage(cell->m_gateOut ? 10 : 0); + } + } + + outputs[x_gridIdOutId].setVoltage(m_switcher.m_gridId); + outputs[x_activeGridIdOutId].setVoltage(m_switcher.m_selectedGridId); + } + + void process(const ProcessArgs &args) override + { + m_switcher.ProcessStatic(args.sampleTime); + if (m_periodChecker.Process(args.sampleTime)) + { + ReadState(); + m_switcher.GetMenuGrid()->ProcessInput(m_state); + SetOutputs(); + } + } +}; + +template +struct GridJnctWidget : ModuleWidget +{ + static constexpr float x_sep = 25; + static constexpr float x_xStart = 50; + static constexpr float x_yStart = 350; + + Vec GetPos(MenuButtonRow::RowPos pos, size_t ix, bool isIn) + { + float x; + float y; + + if (pos == MenuButtonRow::RowPos::Left || + pos == MenuButtonRow::RowPos::Right) + { + y = x_yStart - x_sep * ix - 4 * x_sep; + if (pos == MenuButtonRow::RowPos::Left) + { + x = x_xStart; + if (!isIn) + { + x += x_sep; + } + } + else + { + x = x_xStart + x_gridSize * x_sep + 3 * x_sep; + if (!isIn) + { + x -= x_sep; + } + } + } + else + { + x = x_xStart + x_sep * ix + 2 * x_sep; + if (pos == MenuButtonRow::RowPos::Top) + { + y = x_yStart - x_sep * x_gridSize - 5 * x_sep; + if (!isIn) + { + y += x_sep; + } + } + else + { + y = x_yStart - 3 * x_sep; + if (pos == MenuButtonRow::RowPos::SubBottom) + { + y += 2 * x_sep; + } + + if (!isIn) + { + y -= x_sep; + } + } + } + + return Vec(x, y); + } + + GridJnctWidget(GridJnct* module) + { + setModule(module); + if (Shape == ControllerShape::LaunchPadProMk3) + { + setPanel(createPanel(asset::plugin(pluginInstance, "res/GridJnctLPP3.svg"))); + } + + for (size_t i = 0; i < module->GetNumIOIds(); ++i) + { + auto pairPos = module->m_switcher.GetMenuGrid()->PairPos(i); + addInput(createInputCentered(GetPos(pairPos.first, pairPos.second, true), module, i)); + addOutput(createOutputCentered(GetPos(pairPos.first, pairPos.second, false), module, i)); + } + + addOutput(createOutputCentered(Vec(125, 100), module, module->x_gridIdOutId)); + addOutput(createOutputCentered(Vec(175, 100), module, module->x_activeGridIdOutId)); + } +}; + +struct GridCnct : public Module +{ + MidiInterchangeSingle m_midi; + size_t m_gridId; + GridCnct() + : m_midi(false) + { + m_gridId = x_numGridIds; + config(0, 1, 0, 0); + } + + void process(const ProcessArgs& args) override + { + size_t gridId; + if (inputs[0].isConnected()) + { + gridId = static_cast(inputs[0].getVoltage() + 0.5); + } + else + { + gridId = x_numGridIds; + } + + if (gridId > x_numGridIds) + { + gridId = x_numGridIds; + } + + if (gridId != m_gridId) + { + m_midi.ClearLastSent(); + m_gridId = gridId; + } + + if (m_gridId == x_numGridIds) + { + m_midi.Drain(args.frame); + } + + if (m_gridId != x_numGridIds) + { + m_midi.ApplyMidiToBus(args.frame, m_gridId); + m_midi.SendMidiFromBus(args.frame, m_gridId); + } + } + + json_t* dataToJson() override + { + json_t* rootJ = json_object(); + json_object_set_new(rootJ, "midiIn", m_midi.m_input.toJson()); + json_object_set_new(rootJ, "midiOut", m_midi.m_output.toJson()); + return rootJ; + } + + void dataFromJson(json_t* rootJ) override + { + json_t* midiJ = json_object_get(rootJ, "midiIn"); + if (midiJ) + { + m_midi.m_input.fromJson(midiJ); + } + + midiJ = json_object_get(rootJ, "midiOut"); + if (midiJ) + { + m_midi.m_output.fromJson(midiJ); + } + } +}; + +struct GridCnctWidget : public ModuleWidget +{ + GridCnctWidget(GridCnct* module) + { + setModule(module); + setPanel(createPanel(asset::plugin(pluginInstance, "res/PolyCV_MIDICC.svg"))); + + addChild(createWidget(Vec(RACK_GRID_WIDTH, 0))); + addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0))); + addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); + + StoermelderPackOne::MidiWidget<>* midiInputWidget = createWidget>(Vec(10.0f, 36.4f)); + midiInputWidget->box.size = Vec(130.0f, 67.0f); + midiInputWidget->setMidiPort(module ? &module->m_midi.m_input : NULL); + addChild(midiInputWidget); + + StoermelderPackOne::MidiWidget<>* midiOutputWidget = createWidget>(Vec(10.0f, 107.4f)); + midiOutputWidget->box.size = Vec(130.0f, 67.0f); + midiOutputWidget->setMidiPort(module ? &module->m_midi.m_output : NULL); + addChild(midiOutputWidget); + + addInput(createInputCentered(mm2px(Vec(50, 50)), module, 0)); + + } +}; + +typedef GridJnct GridJnctLPP3; +typedef GridJnctWidget GridJnctLPP3Widget; } diff --git a/private/src/LedDisplayCenterChoiceEx.hpp b/private/src/LedDisplayCenterChoiceEx.hpp new file mode 100644 index 0000000..95100bd --- /dev/null +++ b/private/src/LedDisplayCenterChoiceEx.hpp @@ -0,0 +1,40 @@ +#pragma once +#include "plugin.hpp" + +namespace StoermelderPackOne { + +struct LedDisplayCenterChoiceEx : LedDisplayChoice { + LedDisplayCenterChoiceEx() { + box.size = mm2px(math::Vec(0, 28.0 / 3)); + color = nvgRGB(0xf0, 0xf0, 0xf0); + bgColor = nvgRGBAf(0, 0, 0, 0); + textOffset = math::Vec(0, 18); + } + + void drawLayer(const DrawArgs& args, int layer) override { + nvgScissor(args.vg, RECT_ARGS(args.clipBox)); + if (layer == 1) { + if (bgColor.a > 0.0) { + nvgBeginPath(args.vg); + nvgRect(args.vg, 0, 0, box.size.x, box.size.y); + nvgFillColor(args.vg, bgColor); + nvgFill(args.vg); + } + + std::shared_ptr font = APP->window->loadFont(fontPath); + if (font && font->handle >= 0 && !text.empty()) { + nvgFillColor(args.vg, color); + nvgFontFaceId(args.vg, font->handle); + nvgTextLetterSpacing(args.vg, -0.6f); + nvgFontSize(args.vg, 12); + nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_BOTTOM); + NVGtextRow textRow; + nvgTextBreakLines(args.vg, text.c_str(), NULL, box.size.x, &textRow, 1); + nvgTextBox(args.vg, textOffset.x, textOffset.y, box.size.x, textRow.start, textRow.end); + } + } + nvgResetScissor(args.vg); + } +}; + +} // namespace StoermelderPackOne \ No newline at end of file diff --git a/private/src/MidiWidget.hpp b/private/src/MidiWidget.hpp new file mode 100644 index 0000000..1450fdf --- /dev/null +++ b/private/src/MidiWidget.hpp @@ -0,0 +1,189 @@ +#pragma once +#include "plugin.hpp" +#include "LedDisplayCenterChoiceEx.hpp" + +namespace StoermelderPackOne { + + +struct MidiDriverItem : ui::MenuItem { + midi::Port* port; + int driverId; + void onAction(const event::Action& e) override { + port->setDriverId(driverId); + } +}; + +template +struct MidiDriverChoice : LedDisplayCenterChoiceEx { + midi::Port* port; + void onAction(const event::Action& e) override { + if (!port) + return; + createContextMenu(); + } + + virtual ui::Menu* createContextMenu() { + ui::Menu* menu = createMenu(); + menu->addChild(createMenuLabel("MIDI driver")); + for (int driverId : midi::getDriverIds()) { + DRIVERITEM* item = new DRIVERITEM; + item->port = port; + item->driverId = driverId; + item->text = midi::getDriver(driverId)->getName(); + item->rightText = CHECKMARK(item->driverId == port->driverId); + menu->addChild(item); + } + return menu; + } + + void step() override { + text = port ? port->getDriver()->getName() : ""; + if (text.empty()) { + text = "(No driver)"; + color.a = 0.5f; + } + else { + color.a = 1.f; + } + } +}; + + +struct MidiDeviceItem : ui::MenuItem { + midi::Port* port; + int deviceId; + void onAction(const event::Action& e) override { + port->setDeviceId(deviceId); + } +}; + +template +struct MidiDeviceChoice : LedDisplayCenterChoiceEx { + midi::Port* port; + void onAction(const event::Action& e) override { + if (!port) + return; + createContextMenu(); + } + + virtual ui::Menu* createContextMenu() { + ui::Menu* menu = createMenu(); + menu->addChild(createMenuLabel("MIDI device")); + { + DEVICEITEM* item = new DEVICEITEM; + item->port = port; + item->deviceId = -1; + item->text = "(No device)"; + item->rightText = CHECKMARK(item->deviceId == port->deviceId); + menu->addChild(item); + } + for (int deviceId : port->getDeviceIds()) { + DEVICEITEM* item = new DEVICEITEM; + item->port = port; + item->deviceId = deviceId; + item->text = port->getDeviceName(deviceId); + item->rightText = CHECKMARK(item->deviceId == port->deviceId); + menu->addChild(item); + } + return menu; + } + + void step() override { + text = port ? port->getDeviceName(port->deviceId) : ""; + if (text.empty()) { + text = "(No device)"; + color.a = 0.5f; + } + else { + color.a = 1.f; + } + } +}; + + +struct MidiChannelItem : ui::MenuItem { + midi::Port* port; + int channel; + void onAction(const event::Action& e) override { + port->channel = channel; + } +}; + +template +struct MidiChannelChoice : LedDisplayCenterChoiceEx { + midi::Port* port; + void onAction(const event::Action& e) override { + if (!port) + return; + createContextMenu(); + } + + virtual ui::Menu* createContextMenu() { + ui::Menu* menu = createMenu(); + menu->addChild(createMenuLabel("MIDI channel")); + for (int channel : port->getChannels()) { + CHANNELITEM* item = new CHANNELITEM; + item->port = port; + item->channel = channel; + item->text = port->getChannelName(channel); + item->rightText = CHECKMARK(item->channel == port->channel); + menu->addChild(item); + } + return menu; + } + + void step() override { + text = port ? port->getChannelName(port->channel) : "Channel 1"; + } +}; + + +template , class TDEVICE = MidiDeviceChoice<>, class TCHANNEL = MidiChannelChoice<>> +struct MidiWidget : LedDisplay { + TDRIVER* driverChoice; + LedDisplaySeparator* driverSeparator; + TDEVICE* deviceChoice; + LedDisplaySeparator* deviceSeparator; + TCHANNEL* channelChoice; + + void setMidiPort(midi::Port* port) { + clearChildren(); + math::Vec pos; + + TDRIVER* driverChoice = createWidget(pos); + driverChoice->box.size = Vec(box.size.x, 22.15f); + //driverChoice->textOffset = Vec(6.f, 14.7f); + driverChoice->color = nvgRGB(0xf0, 0xf0, 0xf0); + driverChoice->port = port; + addChild(driverChoice); + pos = driverChoice->box.getBottomLeft(); + this->driverChoice = driverChoice; + + this->driverSeparator = createWidget(pos); + this->driverSeparator->box.size.x = box.size.x; + addChild(this->driverSeparator); + + TDEVICE* deviceChoice = createWidget(pos); + deviceChoice->box.size = Vec(box.size.x, 22.15f); + //deviceChoice->textOffset = Vec(6.f, 14.7f); + deviceChoice->color = nvgRGB(0xf0, 0xf0, 0xf0); + deviceChoice->port = port; + addChild(deviceChoice); + pos = deviceChoice->box.getBottomLeft(); + this->deviceChoice = deviceChoice; + + this->deviceSeparator = createWidget(pos); + this->deviceSeparator->box.size.x = box.size.x; + addChild(this->deviceSeparator); + + TCHANNEL* channelChoice = createWidget(pos); + channelChoice->box.size = Vec(box.size.x, 22.15f); + //channelChoice->textOffset = Vec(6.f, 14.7f); + channelChoice->color = nvgRGB(0xf0, 0xf0, 0xf0); + channelChoice->port = port; + addChild(channelChoice); + this->channelChoice = channelChoice; + } +}; + +} // namespace StoermelderPackOne \ No newline at end of file diff --git a/private/src/SmartGrid.cpp b/private/src/SmartGrid.cpp index c2f1865..c33c0c1 100644 --- a/private/src/SmartGrid.cpp +++ b/private/src/SmartGrid.cpp @@ -3,30 +3,31 @@ namespace SmartGrid { -Color Color::Off(0); -Color Color::Dim(1); -Color Color::Grey(2); -Color Color::White(3); -Color Color::Red(5); -Color Color::DimRed(7); -Color Color::Orange(9); -Color Color::DimOrange(11); -Color Color::Yellow(13); -Color Color::DimYellow(15); -Color Color::Green(21); -Color Color::DimGreen(23); -Color Color::SeaGreen(25); -Color Color::DimSeaGreen(27); -Color Color::Ocean(33); -Color Color::DimOcean(35); -Color Color::Blue(45); -Color Color::DimBlue(47); -Color Color::Fuscia(53); -Color Color::DimFuscia(55); -Color Color::Indigo(80); -Color Color::DimIndigo(104); -Color Color::Purple(81); -Color Color::DimPurple(82); +Color Color::InvalidColor(0, 0, 0, 1); +Color Color::Off(0, 0, 0); +Color Color::Dim(37,37,37); +Color Color::Grey(143,143,143); +Color Color::White(253,253,253); +Color Color::Red(255,40,18); +Color Color::DimRed(34,1,0); +Color Color::Orange(255,108,29); +Color Color::DimOrange(48,31,2); +Color Color::Yellow(255,248,63); +Color Color::DimYellow(32,31,2); +Color Color::Green(9,246,59); +Color Color::DimGreen(0,30,2); +Color Color::SeaGreen(9,246,59); +Color Color::DimSeaGreen(0,30,2); +Color Color::Ocean(0,247,167); +Color Color::DimOcean(0,31,19); +Color Color::Blue(0,60,249); +Color Color::DimBlue(0,2,32); +Color Color::Fuscia(255,71,250); +Color Color::DimFuscia(33,3,32); +Color Color::Indigo(56,61,249); +Color Color::DimIndigo(13,47,107); +Color Color::Purple(134,63,249); +Color Color::DimPurple(194,52,142); ColorScheme ColorScheme::Whites(std::vector({Color::Dim, Color::Grey, Color::White})); ColorScheme ColorScheme::Rainbow(std::vector({ @@ -37,9 +38,9 @@ ColorScheme ColorScheme::Rainbow(std::vector({ Color::Blue, Color::Indigo, Color::Purple})); -ColorScheme ColorScheme::Reds(std::vector({4, 94, 57})); -ColorScheme ColorScheme::Greens(std::vector({24, 123, 65})); -ColorScheme ColorScheme::Blues(std::vector({44, 78, 40})); +ColorScheme ColorScheme::Reds(std::vector({Color(255,101,92), Color(218,70,250), Color(255,44,101)})); +ColorScheme ColorScheme::Greens(std::vector({Color(67,247,104), Color(1,79,12), Color(0,101,67)})); +ColorScheme ColorScheme::Blues(std::vector({Color(79,105,250), Color(0,184,252), Color(73,158,251)})); ColorScheme ColorScheme::RedHues = ColorScheme::Hues(Color::Red); ColorScheme ColorScheme::OrangeHues = ColorScheme::Hues(Color::Orange); ColorScheme ColorScheme::YellowHues = ColorScheme::Hues(Color::Yellow); diff --git a/private/src/SmartGrid.hpp b/private/src/SmartGrid.hpp index 024412a..2245b19 100644 --- a/private/src/SmartGrid.hpp +++ b/private/src/SmartGrid.hpp @@ -16,26 +16,52 @@ static constexpr size_t x_maxChannels = 8; struct Color { constexpr Color() - : m_color(0) + : m_red(0) + , m_green(0) + , m_blue(0) + , m_unused(1) { } - constexpr Color(uint8_t c) : m_color(c) + constexpr Color(uint8_t r, uint8_t g, uint8_t b) + : m_red(r) + , m_green(g) + , m_blue(b) + , m_unused(0) { } - bool operator == (const Color& c) + constexpr Color(uint8_t r, uint8_t g, uint8_t b, uint8_t u) + : m_red(r) + , m_green(g) + , m_blue(b) + , m_unused(u) { - return m_color == c.m_color; } - bool operator != (const Color& c) + uint32_t To32Bit() const { - return m_color != c.m_color; + return (m_red << 24) | (m_green << 16) | (m_blue << 8) | m_unused; } + + bool operator == (const Color& c) const + { + return To32Bit() == c.To32Bit(); + } + + bool operator != (const Color& c) const + { + return !(*this == c); + } + + uint8_t ToLPVelocity(); - uint8_t m_color; + uint8_t m_red; + uint8_t m_green; + uint8_t m_blue; + uint8_t m_unused; + static Color InvalidColor; static Color Off; static Color Dim; static Color Grey; @@ -90,8 +116,22 @@ struct ColorScheme static ColorScheme Hues(Color c) { - uint8_t cbit = c.m_color; - return ColorScheme(std::vector({cbit + 2, cbit + 1, cbit})); + uint8_t maxPrime = std::max(c.m_red, std::max(c.m_green, c.m_blue)); + c.m_red *= 255 / maxPrime; + c.m_green *= 255 / maxPrime; + c.m_blue *= 255 / maxPrime; + + std::vector result; + while (c.m_red > 8 || c.m_green > 8 || c.m_blue > 8) + { + result.push_back(c); + c.m_red /= 2; + c.m_green /= 2; + c.m_blue /= 2; + } + + std::reverse(result.begin(), result.end()); + return ColorScheme(result); } std::vector m_colors; @@ -546,7 +586,7 @@ struct Message { msg.setStatus(0xb); msg.setNote(LPPosToNote(m_x, m_y)); - msg.setValue(m_color.m_color); + msg.setValue(m_color.ToLPVelocity()); msg.setChannel(1); } }; @@ -1407,36 +1447,47 @@ struct MidiInterchangeSingle midi::InputQueue m_input; midi::Output m_output; int m_device; + bool m_isLoopback; static constexpr size_t x_maxNote = 128; - uint8_t m_lastSent[x_maxNote]; + Color m_lastSent[x_maxNote]; MidiInterchangeSingle() + : MidiInterchangeSingle(true) + { + } + + MidiInterchangeSingle(bool isLoopback) : m_device(-1) + , m_isLoopback(isLoopback) { - Init(); + if (m_isLoopback) + { + Init(); + } + + ClearLastSent(); } static constexpr int x_loopbackId = -12; bool IsActive() { - return m_device >= 0; + return !m_isLoopback || m_device >= 0; } void Init() { m_input.setDriverId(x_loopbackId); m_output.setDriverId(x_loopbackId); - ClearLastSent(); } void ClearLastSent() { for (size_t i = 0; i < x_maxNote; ++i) { - m_lastSent[i] = 0xFF; + m_lastSent[i] = Color::InvalidColor; } } @@ -1479,10 +1530,10 @@ struct MidiInterchangeSingle message.PopulateMessage(msg); msg.setFrame(frame); - if (m_lastSent[msg.getNote()] == 0xFF || m_lastSent[msg.getNote()] != message.m_velocity) + if (m_lastSent[msg.getNote()] == Color::InvalidColor || m_lastSent[msg.getNote()] != message.m_color) { m_output.sendMessage(msg); - m_lastSent[msg.getNote()] = message.m_color.m_color; + m_lastSent[msg.getNote()] = message.m_color; } } @@ -1497,10 +1548,10 @@ struct MidiInterchangeSingle message.PopulateMessage(msg); msg.setFrame(frame); - if (m_lastSent[msg.getNote()] != 0xFF) + if (m_lastSent[msg.getNote()] != Color::InvalidColor) { m_output.sendMessage(msg); - m_lastSent[msg.getNote()] = message.m_color.m_color; + m_lastSent[msg.getNote()] = message.m_color; } } @@ -1539,6 +1590,23 @@ struct MidiInterchangeSingle } } + void ApplyMidiToBus(int64_t frame, size_t gridId) + { + if (gridId != x_numGridIds) + { + while (true) + { + Message msg = Pop(frame); + if (msg.NoMessage()) + { + break; + } + + g_smartBus.PutVelocity(gridId, msg.m_x, msg.m_y, msg.m_velocity); + } + } + } + void ApplyMidi(int64_t frame, AbstractGrid* grid) { while (true) @@ -1553,6 +1621,21 @@ struct MidiInterchangeSingle } } + void SendMidiFromBus(int64_t frame, size_t gridId) + { + if (gridId != x_numGridIds) + { + for (auto itr = g_smartBus.OutputBegin(gridId, false /*ignoreChanged*/); itr != g_smartBus.OutputEnd(); ++itr) + { + Message msg = *itr; + if (!msg.NoMessage()) + { + Send(msg, frame); + } + } + } + } + void SendMidi(int64_t frame, AbstractGrid* grid) { for (int i = x_gridXMin; i < x_gridXMax; ++i) @@ -1754,7 +1837,7 @@ struct SmartGrid enum class ControllerShape : int { LaunchPadX = 0, - LaunchPadPro = 1 + LaunchPadProMk3 = 1 }; } diff --git a/private/src/TheNonagon.hpp b/private/src/TheNonagon.hpp index d956bc4..ec670ff 100644 --- a/private/src/TheNonagon.hpp +++ b/private/src/TheNonagon.hpp @@ -1182,8 +1182,7 @@ struct TheNonagonSmartGrid TheNonagonInternal* m_nonagon; TheNonagonSmartGrid* m_owner; TheNonagonGridSwitcher(TheNonagonSmartGrid* owner) - : MenuGridSwitcher(new SmartGrid::MenuGrid()) - , m_state(&owner->m_state) + : m_state(&owner->m_state) , m_nonagon(&owner->m_nonagon) , m_owner(owner) { diff --git a/private/src/plugin.cpp b/private/src/plugin.cpp index 4d87ee4..0f9d174 100644 --- a/private/src/plugin.cpp +++ b/private/src/plugin.cpp @@ -17,6 +17,9 @@ void init(Plugin* p) { p->addModel(modelTheoryOfTime); p->addModel(modelTheNonagon); p->addModel(modelPhasorEnvelope); + p->addModel(modelGridJnctLPP3); + p->addModel(modelGridCnct); + p->addModel(modelFaderBank); // Any other plugin initialization may go here. // As an alternative, consider lazy-loading assets and lookup tables when your module is created to reduce startup times of Rack. diff --git a/private/src/plugin.hpp b/private/src/plugin.hpp index bcc1ff9..3b8a16e 100644 --- a/private/src/plugin.hpp +++ b/private/src/plugin.hpp @@ -16,7 +16,10 @@ extern Model* modelMultiPhasorGate; extern Model* modelGangedRandomLFO; extern Model* modelTheoryOfTime; extern Model* modelTheNonagon; +extern Model* modelGridJnctLPP3; extern Model* modelPhasorEnvelope; +extern Model* modelGridCnct; +extern Model* modelFaderBank; template struct Grid16MidiDisplay : MidiDisplay {