From e73189c0e748c9f9e9f04f2a98c280d71e066dc8 Mon Sep 17 00:00:00 2001 From: Colin Sullivan Date: Thu, 4 May 2023 12:54:35 -0700 Subject: [PATCH] An initial implementation of a Control UI for the daisy patch init device --- architecture/daisy/ex_faust.cpp | 16 ++ .../faust/gui/DaisyPatchInitControlUI.h | 213 ++++++++++++++++++ tools/faust2appls/faust2daisy | 7 + 3 files changed, 236 insertions(+) create mode 100644 architecture/faust/gui/DaisyPatchInitControlUI.h diff --git a/architecture/daisy/ex_faust.cpp b/architecture/daisy/ex_faust.cpp index b2f2979965..5d87125961 100644 --- a/architecture/daisy/ex_faust.cpp +++ b/architecture/daisy/ex_faust.cpp @@ -38,13 +38,19 @@ #include "daisy_patch.h" #elif defined POD #include "daisy_pod.h" +#elif defined PATCHSM +#include "daisy_patch_sm.h" #else #include "daisy_seed.h" #endif #include "faust/gui/meta.h" #include "faust/gui/UI.h" +#if defined PATCHSM +#include "faust/gui/DaisyPatchInitControlUI.h" +#else #include "faust/gui/DaisyControlUI.h" +#endif #include "faust/dsp/dsp.h" #ifdef MIDICTRL @@ -83,11 +89,17 @@ using namespace std; static daisy::DaisyPatch hw; #elif defined POD static daisy::DaisyPod hw; +#elif defined PATCHSM +static daisy::patch_sm::DaisyPatchSM hw; #else static daisy::DaisySeed hw; #endif +#if defined PATCHSM +static DaisyPatchInitControlUI* control_UI = nullptr; +#else static DaisyControlUI* control_UI = nullptr; +#endif static dsp* DSP = nullptr; #ifdef MIDICTRL @@ -131,6 +143,10 @@ int main(void) control_UI = new DaisyControlUI(&hw.seed, MY_SAMPLE_RATE/MY_BUFFER_SIZE); DSP->buildUserInterface(control_UI); hw.StartAdc(); +#elif defined (PATCHSM) + control_UI = new DaisyPatchInitControlUI(&hw, MY_SAMPLE_RATE/MY_BUFFER_SIZE); + DSP->buildUserInterface(control_UI); + hw.StartAdc(); #else //initialize UI for seed control_UI = new DaisyControlUI(&hw, MY_SAMPLE_RATE/MY_BUFFER_SIZE); diff --git a/architecture/faust/gui/DaisyPatchInitControlUI.h b/architecture/faust/gui/DaisyPatchInitControlUI.h new file mode 100644 index 0000000000..fd47159156 --- /dev/null +++ b/architecture/faust/gui/DaisyPatchInitControlUI.h @@ -0,0 +1,213 @@ +#ifndef FAUST_DAISYPATCHINITCONTROL_H +#define FAUST_DAISYPATCHINITCONTROL_H + +#include +#include +#include +#include + +#include "daisysp.h" +#include "daisy_seed.h" + +#include "faust/gui/DecoratorUI.h" +#include "faust/gui/ValueConverter.h" + +/******************************************************************************* + * DaisyPatchInitControlUI : Faust User Interface + ******************************************************************************/ + +class DaisyPatchInitControlUI : public GenericUI +{ + + private: + + // Base class for updatable items + struct UpdatableZone { + FAUSTFLOAT* fZone; + + UpdatableZone(FAUSTFLOAT* zone) : fZone(zone) {} + virtual ~UpdatableZone() {} + + virtual void update() = 0; + }; + + struct SwitchButton : daisy::Switch, UpdatableZone { + + SwitchButton(FAUSTFLOAT* zone):UpdatableZone(zone) + {} + + void update() + { + *fZone = RawState(); + } + }; + + // Implement checkbox using daisy::Switch + struct CheckButton : daisy::Switch, UpdatableZone { + + FAUSTFLOAT fLastButton; + + CheckButton(FAUSTFLOAT* zone):UpdatableZone(zone), fLastButton(0) + {} + + void update() + { + FAUSTFLOAT button = RawState(); + if (button == 1.0 && (button != fLastButton)) { + *fZone = !*fZone; + } + fLastButton = button; + } + }; + + // Implements an analog knob by calling Process on the knob instance + // that has already been created inside DaisyPatchSM + struct AnalogKnob : UpdatableZone { + + std::unique_ptr fConverter; + daisy::AnalogControl* fControl; + + AnalogKnob(daisy::AnalogControl* control, FAUSTFLOAT* zone, std::unique_ptr& converter, int rate) + : UpdatableZone(zone), fConverter(std::move(converter)), fControl(control) + { + } + + void update() + { + *fZone = fConverter->ui2faust(fControl->Process()); + } + }; + + std::vector> fItems; + daisy::patch_sm::DaisyPatchSM* fHw; + + std::string fKey, fValue, fScale; + int fRate, fBoxLevel; + + struct KnobContext + { + int fKnobId; + FAUSTFLOAT* fZone; + FAUSTFLOAT fMin; + FAUSTFLOAT fMax; + std::string fScale; + KnobContext(int kid, + FAUSTFLOAT* zone, + FAUSTFLOAT min, + FAUSTFLOAT max, + const std::string& scale) + :fKnobId(kid), fZone(zone), fMin(min), fMax(max), fScale(scale) + {} + }; + std::vector fKnobs; + + void InitKnob(int knob_pin, FAUSTFLOAT* zone, FAUSTFLOAT min, FAUSTFLOAT max, const std::string& scale) + { + // context is kept, to be used in InitKnobs() + fKnobs.push_back(KnobContext(knob_pin, zone, min, max, scale)); + } + + void InitKnobs() + { + for (size_t i = 0; i < fKnobs.size(); i++) { + std::unique_ptr converter; + if (fKnobs[i].fScale == "log") { + converter = std::make_unique(0., 1., fKnobs[i].fMin, fKnobs[i].fMax); + } else if (fKnobs[i].fScale == "exp") { + converter = std::make_unique(0., 1., fKnobs[i].fMin, fKnobs[i].fMax); + } else { + converter = std::make_unique(0., 1., fKnobs[i].fMin, fKnobs[i].fMax); + } + std::unique_ptr knob = std::make_unique(&fHw->controls[fKnobs[i].fKnobId], + fKnobs[i].fZone, + converter, + fRate); + fItems.push_back(std::move(knob)); + } + } + + public: + + DaisyPatchInitControlUI(daisy::patch_sm::DaisyPatchSM* hw, int rate) + :fHw(hw), fScale("lin"),fRate(rate), fBoxLevel(0) + {} + + // -- widget's layouts + void openTabBox(const char* label) { fBoxLevel++; } + void openHorizontalBox(const char* label) { fBoxLevel++; } + void openVerticalBox(const char* label) { fBoxLevel++; } + void closeBox() + { + if (--fBoxLevel == 0) InitKnobs(); + } + + // -- active widgets + void addButton(const char* label, FAUSTFLOAT* zone) + { + if (fKey == "switch") { + std::unique_ptr button = std::make_unique(zone); + //if (fValue == "1") { + //button->Init(fSeed->GetPin(SW_1_PIN), fRate); + //} + fItems.push_back(std::move(button)); + } + fValue = fKey = fScale = ""; + } + + void addCheckButton(const char* label, FAUSTFLOAT* zone) + { + if (fKey == "switch") { + std::unique_ptr button = std::make_unique(zone); + //if (fValue == "1") { + //button->Init(fSeed->GetPin(SW_1_PIN), fRate); + //} + fItems.push_back(std::move(button)); + } + fValue = fKey = fScale = ""; + } + + void addVerticalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addNumEntry(label, zone, init, min, max, step); + } + void addHorizontalSlider(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + addNumEntry(label, zone, init, min, max, step); + } + void addNumEntry(const char* label, FAUSTFLOAT* zone, FAUSTFLOAT init, FAUSTFLOAT min, FAUSTFLOAT max, FAUSTFLOAT step) + { + if (fKey == "knob") { + if (fValue == "1") { + InitKnob(daisy::patch_sm::CV_1, zone, min, max, fScale); + } else if (fValue == "2") { + InitKnob(daisy::patch_sm::CV_2, zone, min, max, fScale); + } else if (fValue == "3") { + InitKnob(daisy::patch_sm::CV_3, zone, min, max, fScale); + } else if (fValue == "4") { + InitKnob(daisy::patch_sm::CV_4, zone, min, max, fScale); + } + } + fValue = fKey = fScale = ""; + } + + // -- metadata declarations + void declare(FAUSTFLOAT* zone, const char* key, const char* val) + { + if (strcmp(key, "switch") == 0 + || strcmp(key, "knob") == 0) { + fKey = key; + fValue = val; + } else if (std::string(key) == "scale") { + fScale = val; + } + } + + void update() + { + for (const auto& it : fItems) it->update(); + } + +}; + +#endif // FAUST_DAISYPATCHINITCONTROL_H +/************************** END DaisyPatchInitControlUI.h **************************/ diff --git a/tools/faust2appls/faust2daisy b/tools/faust2appls/faust2daisy index 9e639fa9a4..2e10d15e1c 100755 --- a/tools/faust2appls/faust2daisy +++ b/tools/faust2appls/faust2daisy @@ -35,6 +35,7 @@ echoHelp () option option -patch "to compile for 4 ins/outs Patch (knob[1,2,3,4])" option -pod "to compile for 2 ins/outs Pod (knob[1,3])" + option -patchsm "to compile for the Pod.init eurorack module" options -midi option "-nvoices " option "-sr " @@ -73,6 +74,8 @@ do PATCH=true elif [ $p = "-pod" ]; then POD=true + elif [ $p = "-patchsm" ]; then + PATCHSM=true # -sr elif [ $p = "-sr" ]; then shift @@ -120,6 +123,10 @@ for p in $FILE; do if [ $POD == true ]; then echo "#define POD" | cat - "$SRCDIR/$dspName/ex_faust.cpp" > temp && mv temp "$SRCDIR/$dspName/ex_faust.cpp" fi + # for PODSM support + if [ $PATCHSM == true ]; then + echo "#define PATCHSM" | cat - "$SRCDIR/$dspName/ex_faust.cpp" > temp && mv temp "$SRCDIR/$dspName/ex_faust.cpp" + fi # for MIDI if [ $MIDI == true ]; then