diff --git a/src/common/SurgePatch.cpp b/src/common/SurgePatch.cpp index 4c9c88b3111..a092668630e 100644 --- a/src/common/SurgePatch.cpp +++ b/src/common/SurgePatch.cpp @@ -766,6 +766,13 @@ void SurgePatch::init_default_values() { strxcpy(CustomControllerLabel[i], "-", CUSTOM_CONTROLLER_LABEL_SIZE); } + for (int i = 0; i < n_lfos; ++i) + { + for (int d = 0; d < max_lfo_indices; ++d) + { + LFOBankLabel[i][d][0] = 0; + } + } } SurgePatch::~SurgePatch() { free(patchptr); } @@ -2015,6 +2022,28 @@ void SurgePatch::load_xml(const void *data, int datasize, bool is_preset) p = TINYXML_SAFE_TO_ELEMENT(p->NextSibling("entry")); } + for (int i = 0; i < n_lfos; ++i) + { + for (int d = 0; d < max_lfo_indices; ++d) + { + LFOBankLabel[i][d][0] = 0; + } + } + + TiXmlElement *lflb = TINYXML_SAFE_TO_ELEMENT(patch->FirstChild("lfobanklabels")); + if (lflb) + { + auto lb = TINYXML_SAFE_TO_ELEMENT(lflb->FirstChild("label")); + while (lb) + { + int lfo, idx; + if (lb->QueryIntAttribute("lfo", &lfo) == TIXML_SUCCESS && + lb->QueryIntAttribute("idx", &idx) == TIXML_SUCCESS) + strxcpy(LFOBankLabel[lfo][idx], lb->Attribute("v"), CUSTOM_CONTROLLER_LABEL_SIZE); + lb = TINYXML_SAFE_TO_ELEMENT(lb->NextSibling("label")); + } + } + patchTuning.tuningStoredInPatch = false; patchTuning.scaleContents = ""; patchTuning.mappingContents = ""; @@ -2564,6 +2593,21 @@ unsigned int SurgePatch::save_xml(void **data) // allocates mem, must be freed b } patch.InsertEndChild(cc); + TiXmlElement lfobank("lfobanklabels"); + for (int i = 0; i < n_lfos; ++i) + for (int d = 0; d < max_lfo_indices; ++d) + { + if (LFOBankLabel[i][d][0] != 0) + { + TiXmlElement L("label"); + L.SetAttribute("lfo", i); + L.SetAttribute("idx", d); + L.SetAttribute("v", LFOBankLabel[i][d]); + lfobank.InsertEndChild(L); + } + } + patch.InsertEndChild(lfobank); + { char txt[TXT_SIZE]; TiXmlElement mw("modwheel"); diff --git a/src/common/SurgeStorage.h b/src/common/SurgeStorage.h index 723c5cb9830..fa7a21dcc87 100644 --- a/src/common/SurgeStorage.h +++ b/src/common/SurgeStorage.h @@ -53,6 +53,7 @@ const int n_oscs = 3; const int n_lfos_voice = 6; const int n_lfos_scene = 6; const int n_lfos = n_lfos_voice + n_lfos_scene; +const int max_lfo_indices = 8; const int n_osc_params = 7; const int n_egs = 2; const int n_fx_params = 12; @@ -848,6 +849,8 @@ class SurgePatch #define CUSTOM_CONTROLLER_LABEL_SIZE 20 char CustomControllerLabel[n_customcontrollers][CUSTOM_CONTROLLER_LABEL_SIZE]; + char LFOBankLabel[n_lfos][max_lfo_indices][CUSTOM_CONTROLLER_LABEL_SIZE]; + int streamingRevision; int currentSynthStreamingRevision; diff --git a/src/common/dsp/modulators/FormulaModulationHelper.h b/src/common/dsp/modulators/FormulaModulationHelper.h index a61626171d1..c203b0a2d75 100644 --- a/src/common/dsp/modulators/FormulaModulationHelper.h +++ b/src/common/dsp/modulators/FormulaModulationHelper.h @@ -27,7 +27,7 @@ namespace Surge { namespace Formula { -static constexpr int max_formula_outputs{8}; +static constexpr int max_formula_outputs{max_lfo_indices}; struct EvaluatorState { diff --git a/src/surge-xt/gui/SurgeGUIEditor.cpp b/src/surge-xt/gui/SurgeGUIEditor.cpp index 859b6f9eb4a..265bb210487 100644 --- a/src/surge-xt/gui/SurgeGUIEditor.cpp +++ b/src/surge-xt/gui/SurgeGUIEditor.cpp @@ -3872,8 +3872,8 @@ void SurgeGUIEditor::promptForUserValueEntry(Parameter *p, juce::Component *c, i if (ismod) { - std::string mls = std::string("by ") + modulatorName(ms, true) + - modulatorIndexExtension(current_scene, ms, modidx); + std::string mls = + std::string("by ") + modulatorNameWithIndex(current_scene, ms, modidx, true, false); typeinParamEditor->setModByLabel(mls); } @@ -5503,6 +5503,31 @@ std::string SurgeGUIEditor::modulatorIndexExtension(int scene, int ms, int index return ""; } +std::string SurgeGUIEditor::modulatorNameWithIndex(int scene, int ms, int index, bool forButton, + bool useScene) +{ + if (synth->storage.getPatch().LFOBankLabel[ms - ms_lfo1][index][0] == 0) + { + auto base = modulatorName(ms, forButton, useScene ? scene : -1); + if (synth->supportsIndexedModulator(scene, (modsources)ms)) + base += modulatorIndexExtension(scene, ms, index, forButton); + return base; + } + else + { + if (forButton) + return synth->storage.getPatch().LFOBankLabel[ms - ms_lfo1][index]; + + // Long name is alias (button name) + auto base = modulatorName(ms, true, useScene ? scene : -1); + if (synth->supportsIndexedModulator(scene, (modsources)ms)) + base += modulatorIndexExtension(scene, ms, index, true); + std::string res = synth->storage.getPatch().LFOBankLabel[ms - ms_lfo1][index]; + res = res + " (" + base + ")"; + return res; + } +} + void SurgeGUIEditor::setupAlternates(modsources ms) { jassert(gui_modsrc[ms]); @@ -5518,21 +5543,13 @@ void SurgeGUIEditor::setupAlternates(modsources ms) for (auto a : traverse) { - auto baseLabel = modulatorName(a, true); - auto baseLongName = modulatorName(a, false); - int idxc = 1; if (synth->supportsIndexedModulator(current_scene, a)) idxc = synth->getMaxModulationIndex(current_scene, a); for (int q = 0; q < idxc; ++q) { - auto tl = baseLabel; - auto ll = baseLongName; - if (idxc > 1) - { - tl += modulatorIndexExtension(current_scene, a, q, true); - ll += modulatorIndexExtension(current_scene, a, q, false); - } + auto tl = modulatorNameWithIndex(current_scene, a, q, true, false); + auto ll = modulatorNameWithIndex(current_scene, a, q, false, false); indexedAlternates.emplace_back(a, q, tl, ll); } } diff --git a/src/surge-xt/gui/SurgeGUIEditor.h b/src/surge-xt/gui/SurgeGUIEditor.h index ab9b4b5a3eb..7c6b65ff5ee 100644 --- a/src/surge-xt/gui/SurgeGUIEditor.h +++ b/src/surge-xt/gui/SurgeGUIEditor.h @@ -622,6 +622,7 @@ class SurgeGUIEditor : public Surge::GUI::IComponentTagValue::Listener, public: std::string modulatorName(int ms, bool forButton, int forScene = -1); std::string modulatorIndexExtension(int scene, int ms, int index, bool shortV = false); + std::string modulatorNameWithIndex(int scene, int ms, int index, bool forButton, bool useScene); private: Parameter *typeinEditTarget = nullptr; diff --git a/src/surge-xt/gui/SurgeGUIEditorInfowindow.cpp b/src/surge-xt/gui/SurgeGUIEditorInfowindow.cpp index 0b145f6216d..70f83981d50 100644 --- a/src/surge-xt/gui/SurgeGUIEditorInfowindow.cpp +++ b/src/surge-xt/gui/SurgeGUIEditorInfowindow.cpp @@ -93,9 +93,7 @@ void SurgeGUIEditor::updateInfowindowContents(int ptag, bool isModulated) SurgeSynthesizer::ID ptagid; if (synth->fromSynthSideId(pid, ptagid)) synth->getParameterName(ptagid, txt); - auto mn = modulatorName(modsource, true); - if (synth->supportsIndexedModulator(current_scene, modsource)) - mn += modulatorIndexExtension(current_scene, modsource, modsource_index, true); + auto mn = modulatorNameWithIndex(current_scene, modsource, modsource_index, true, false); sprintf(pname, "%s -> %s", mn.c_str(), txt); ModulationDisplayInfoWindowStrings mss; diff --git a/src/surge-xt/gui/SurgeGUIEditorValueCallbacks.cpp b/src/surge-xt/gui/SurgeGUIEditorValueCallbacks.cpp index de2d0b27b4a..01e3d3e0419 100644 --- a/src/surge-xt/gui/SurgeGUIEditorValueCallbacks.cpp +++ b/src/surge-xt/gui/SurgeGUIEditorValueCallbacks.cpp @@ -571,7 +571,8 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c if (lurl != "") lurl = fullyResolvedHelpURL(lurl); auto hmen = std::make_unique( - modulatorName(modsource, false), lurl); + modulatorNameWithIndex(current_scene, modsource, modsource_index, false, false), + lurl); hmen->setSkin(currentSkin, bitmapStore); contextMenu.addCustomItem(-1, std::move(hmen)); @@ -622,6 +623,9 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c for (auto modidx : indices) { + if (hasIdx && modidx != modsource_index) + continue; + if (first_destination) { contextMenu.addSeparator(); @@ -846,13 +850,6 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c } int sc = limit_range(synth->storage.getPatch().scene_active.val.i, 0, n_scenes - 1); - contextMenu.addSeparator(); - - contextMenu.addItem(Surge::GUI::toOSCaseForMenu("Modulation List..."), [this]() { - if (!isAnyOverlayPresent(MODULATION_EDITOR)) - showOverlay(MODULATION_EDITOR); - }); - // for macros only if (within_range(ms_ctrl1, modsource, ms_ctrl1 + n_customcontrollers - 1)) { @@ -936,6 +933,18 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c if (lfo_id >= 0) { + auto msi = modsource_index; + contextMenu.addItem( + Surge::GUI::toOSCaseForMenu("Rename Modulator"), [this, lfo_id, msi, cms]() { + auto mecb = [this, lfo_id, msi](const std::string &nv) { + auto cp = synth->storage.getPatch().LFOBankLabel[lfo_id][msi]; + strxcpy(cp, nv.c_str(), CUSTOM_CONTROLLER_LABEL_SIZE); + synth->refresh_editor = true; + }; + promptForMiniEdit(synth->storage.getPatch().LFOBankLabel[lfo_id][msi], + "Set Modulator Name", "Rename Modulator", + juce::Point(10, 10), mecb); + }); contextMenu.addItem(Surge::GUI::toOSCaseForMenu("Copy Modulator"), [this, sc, lfo_id]() { synth->storage.clipboard_copy(cp_lfo, sc, lfo_id); @@ -1929,13 +1938,8 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c modtxt, synth->getModDepth(ptag, ms, sc, modidx), synth->isBipolarModulation(ms), Parameter::Menu); - char srctxt[512]; - - sprintf( - srctxt, "%s%s", - (char *)modulatorName(ms, true, showScene ? sc : -1) - .c_str(), - modulatorIndexExtension(current_scene, ms, modidx).c_str()); + std::string srctxt = modulatorNameWithIndex( + current_scene, ms, modidx, true, showScene); auto comp = std::make_unique( @@ -2087,8 +2091,8 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c auto subm = juce::PopupMenu(); for (int i = 0; i < maxidx; ++i) { - auto subn = modulatorName(ms, false) + - modulatorIndexExtension(current_scene, ms, i); + auto subn = + modulatorNameWithIndex(current_scene, ms, i, false, false); subm.addItem(subn, [this, p, bvf, ms, i]() { this->promptForUserValueEntry(p, bvf, ms, current_scene, i); }); @@ -2141,11 +2145,6 @@ int32_t SurgeGUIEditor::controlModifierClicked(Surge::GUI::IComponentTagValue *c } } - contextMenu.addItem(Surge::GUI::toOSCaseForMenu("Modulation List..."), [this]() { - if (!isAnyOverlayPresent(MODULATION_EDITOR)) - showOverlay(MODULATION_EDITOR); - }); - contextMenu.addSeparator(); createMIDILearnMenuEntries(contextMenu, false, p->id, control); diff --git a/src/surge-xt/gui/overlays/ModulationEditor.cpp b/src/surge-xt/gui/overlays/ModulationEditor.cpp index 34eddafb9bb..992c3f33133 100644 --- a/src/surge-xt/gui/overlays/ModulationEditor.cpp +++ b/src/surge-xt/gui/overlays/ModulationEditor.cpp @@ -479,11 +479,9 @@ struct ModulationListContents : public juce::Component, public Surge::GUI::SkinC SurgeSynthesizer::ID ptagid; if (synth->fromSynthSideId(d.destination_id + d.idBase, ptagid)) synth->getParameterName(ptagid, nm); - std::string sname = editor->ed->modulatorName(d.source_id, false); - if (d.inScene < 0) - sname = editor->ed->modulatorName(d.source_id, false, d.source_scene); - if (d.inScene >= 0) - sname += editor->ed->modulatorIndexExtension(d.inScene, d.source_id, d.source_index); + + std::string sname = editor->ed->modulatorNameWithIndex( + d.source_scene, d.source_id, d.source_index, false, d.inScene < 0); d.sname = sname + sceneMod; d.pname = nm;