From 0587e2f68ae7e235a54e5ad2fb4974008f5ed657 Mon Sep 17 00:00:00 2001 From: Alex Birch Date: Sat, 20 Jul 2019 18:49:39 +0100 Subject: [PATCH] decided against maintaining a separate 'presets' property in the ValueTree, since this is a view modelling concern that only the table cares about. instead, store as a tree. let the table component be responsible for maintaining a view over a subset of presets, instead of bothering the ValueTree with this. this is an effort to dial back the use of the store, and prefer to use it where it provides the most value rather than using it for everything. --- Source/FluidSynthModel.cpp | 119 ++++++++++++++++++++++++------------- Source/FluidSynthModel.h | 2 +- Source/PluginProcessor.cpp | 2 +- Source/TableComponent.cpp | 77 ++++++++++++++++++++---- Source/TableComponent.h | 7 ++- 5 files changed, 154 insertions(+), 53 deletions(-) diff --git a/Source/FluidSynthModel.cpp b/Source/FluidSynthModel.cpp index 138da22..4fd4891 100644 --- a/Source/FluidSynthModel.cpp +++ b/Source/FluidSynthModel.cpp @@ -234,7 +234,7 @@ void FluidSynthModel::parameterChanged(const String& parameterID, float newValue static_cast(preset)); // fluid_synth_bank_select(synth.get(), channel, value); - refreshPresets(); +// refreshPresets(); // fluid_sfont_t* sfont{fluid_synth_get_sfont_by_id(synth.get(), sfont_id)}; // fluid_sfont_iteration_start(sfont); // fluid_preset_t* presetObj{fluid_sfont_iteration_next(sfont)}; @@ -409,60 +409,99 @@ void FluidSynthModel::refreshBanks() { fluid_sfont_t* sfont {fluid_synth_get_sfont_by_id(synth.get(), sfont_id)}; ValueTree banks{"banks"}; if (sfont != nullptr) { - // int initialBankOffset{fluid_synth_get_bank_offset(synth.get(), sfont_id)}; - banks.appendChild({ "bank", { - { "num", /* initialBankOffset */ 0 }, - }, {} }, nullptr); - // int greatestPersistedBank{initialBankOffset}; - int greatestPersistedBank{0}; + int greatestEncounteredBank{-1}; + ValueTree bank; fluid_sfont_iteration_start(sfont); - for(fluid_preset_t* preset {fluid_sfont_iteration_next(sfont)}; preset != nullptr; preset = fluid_sfont_iteration_next(sfont)) { - int bank{fluid_preset_get_banknum(preset) /* + initialBankOffset */}; - if (bank > greatestPersistedBank) { - banks.appendChild({ "bank", { - { "num", bank }, - }, {} }, nullptr); - greatestPersistedBank = bank; + int bankNum{fluid_preset_get_banknum(preset)}; + if (bankNum > greatestEncounteredBank) { + if (greatestEncounteredBank > -1) { + banks.appendChild(bank, nullptr); + } + bank = { "bank", { + { "num", bankNum } + } }; + greatestEncounteredBank = bankNum; } + bank.appendChild({ "preset", { + { "num", fluid_preset_get_num(preset) }, + { "name", String{fluid_preset_get_name(preset)} } + }, {} }, nullptr); + } + if (greatestEncounteredBank > -1) { + banks.appendChild(bank, nullptr); } } valueTreeState.state.getChildWithName("banks").copyPropertiesAndChildrenFrom(banks, nullptr); valueTreeState.state.getChildWithName("banks").sendPropertyChangeMessage("synthetic"); - refreshPresets(); + +#if JUCE_DEBUG + unique_ptr xml{valueTreeState.state.createXml()}; + Logger::outputDebugString(xml->createDocument("",false,false)); +#endif } -void FluidSynthModel::refreshPresets() { - fluid_sfont_t* sfont {fluid_synth_get_sfont_by_id(synth.get(), sfont_id)}; - ValueTree presets{"presets"}; - if (sfont != nullptr) { - RangedAudioParameter *param {valueTreeState.getParameter("bank")}; - jassert(dynamic_cast (param) != nullptr); - AudioParameterInt* castParam {dynamic_cast (param)}; - int value{castParam->get()}; +// void FluidSynthModel::refreshBanks() { +// fluid_sfont_t* sfont {fluid_synth_get_sfont_by_id(synth.get(), sfont_id)}; +// ValueTree banks{"banks"}; +// if (sfont != nullptr) { +// // int initialBankOffset{fluid_synth_get_bank_offset(synth.get(), sfont_id)}; +// banks.appendChild({ "bank", { +// { "num", /* initialBankOffset */ 0 }, +// }, {} }, nullptr); +// // int greatestPersistedBank{initialBankOffset}; +// int greatestPersistedBank{0}; - // int initialBank{fluid_synth_get_bank_offset(synth.get(), sfont_id)}; +// fluid_sfont_iteration_start(sfont); - fluid_sfont_iteration_start(sfont); +// for(fluid_preset_t* preset {fluid_sfont_iteration_next(sfont)}; +// preset != nullptr; +// preset = fluid_sfont_iteration_next(sfont)) { +// int bank{fluid_preset_get_banknum(preset) /* + initialBankOffset */}; +// if (bank > greatestPersistedBank) { +// banks.appendChild({ "bank", { +// { "num", bank }, +// }, {} }, nullptr); +// greatestPersistedBank = bank; +// } +// } +// } +// valueTreeState.state.getChildWithName("banks").copyPropertiesAndChildrenFrom(banks, nullptr); +// valueTreeState.state.getChildWithName("banks").sendPropertyChangeMessage("synthetic"); +// refreshPresets(); +// } - for(fluid_preset_t* preset {fluid_sfont_iteration_next(sfont)}; - preset != nullptr; - preset = fluid_sfont_iteration_next(sfont)) { - int bank{fluid_preset_get_banknum(preset) /* + initialBank */}; - if (bank == value) { - presets.appendChild({ "preset", { - { "num", fluid_preset_get_num(preset) }, - { "name", String{fluid_preset_get_name(preset)} } - }, {} }, nullptr); - } - } - } - valueTreeState.state.getChildWithName("presets").copyPropertiesAndChildrenFrom(presets, nullptr); - valueTreeState.state.getChildWithName("presets").sendPropertyChangeMessage("synthetic"); -} +// void FluidSynthModel::refreshPresets() { +// fluid_sfont_t* sfont {fluid_synth_get_sfont_by_id(synth.get(), sfont_id)}; +// ValueTree presets{"presets"}; +// if (sfont != nullptr) { +// RangedAudioParameter *param {valueTreeState.getParameter("bank")}; +// jassert(dynamic_cast (param) != nullptr); +// AudioParameterInt* castParam {dynamic_cast (param)}; +// int value{castParam->get()}; + +// // int initialBank{fluid_synth_get_bank_offset(synth.get(), sfont_id)}; + +// fluid_sfont_iteration_start(sfont); + +// for(fluid_preset_t* preset {fluid_sfont_iteration_next(sfont)}; +// preset != nullptr; +// preset = fluid_sfont_iteration_next(sfont)) { +// int bank{fluid_preset_get_banknum(preset) /* + initialBank */}; +// if (bank == value) { +// presets.appendChild({ "preset", { +// { "num", fluid_preset_get_num(preset) }, +// { "name", String{fluid_preset_get_name(preset)} } +// }, {} }, nullptr); +// } +// } +// } +// valueTreeState.state.getChildWithName("presets").copyPropertiesAndChildrenFrom(presets, nullptr); +// valueTreeState.state.getChildWithName("presets").sendPropertyChangeMessage("synthetic"); +// } // void FluidSynthModel::refreshBanksAndPresets() { // fluid_sfont_t* sfont {fluid_synth_get_sfont_by_id(synth.get(), sfont_id)}; diff --git a/Source/FluidSynthModel.h b/Source/FluidSynthModel.h index c5bc48f..92a06e6 100644 --- a/Source/FluidSynthModel.h +++ b/Source/FluidSynthModel.h @@ -105,7 +105,7 @@ private: int handleMidiEvent(void* data, fluid_midi_event_t* event); void refreshBanks(); - void refreshPresets(); + // void refreshPresets(); // void refreshBanksAndPresets(); // ValueTreeListener valueTreeListener; diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index b614540..2ad8085 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -47,7 +47,7 @@ JuicySFAudioProcessor::JuicySFAudioProcessor() { "path", "" }, }, {} }, nullptr); // no properties, no subtrees (yet) - valueTreeState.state.appendChild({ "presets", {}, {} }, nullptr); + // valueTreeState.state.appendChild({ "presets", {}, {} }, nullptr); // no properties, no subtrees (yet) valueTreeState.state.appendChild({ "banks", {}, {} }, nullptr); // valueTreeState.state.setProperty("soundFontPath", "", nullptr); diff --git a/Source/TableComponent.cpp b/Source/TableComponent.cpp index babf668..e067906 100644 --- a/Source/TableComponent.cpp +++ b/Source/TableComponent.cpp @@ -8,6 +8,9 @@ #include "TableComponent.h" #include "Util.h" +#include +#include +#include using namespace std; using namespace Util; @@ -74,8 +77,9 @@ TableComponent::TableComponent( table.setWantsKeyboardFocus(false); // table.selectRow(); - ValueTree presets{valueTreeState.state.getChildWithName("presets")}; - loadModelFrom(presets); + // ValueTree presets{valueTreeState.state.getChildWithName("presets")}; + ValueTree banks{valueTreeState.state.getChildWithName("banks")}; + loadModelFrom(banks); // selectCurrentPreset(); // we could now change some initial settings.. @@ -93,15 +97,63 @@ TableComponent::~TableComponent() { valueTreeState.state.removeListener(this); } -void TableComponent::loadModelFrom(ValueTree& presets) { +// void TableComponent::loadModelFrom(ValueTree& presets) { +// rows.clear(); +// int numChildren{presets.getNumChildren()}; +// for(int i{0}; i presets; + ValueTree bank{banks.getChild(bankIx)}; + int bankNum{bank.getProperty("num")}; + int bankChildren{bank.getNumChildren()}; + for(int presetIx{0}; presetIx(param) != nullptr); + AudioParameterInt* castParam{dynamic_cast(param)}; + int bank{castParam->get()}; + + BanksToPresets::iterator lowerBound{banksToPresets.lower_bound(bank)}; + BanksToPresets::iterator upperBound{banksToPresets.upper_bound(bank)}; + + // basic syntaxes for a lambda which return's a pair's .second + // https://stackoverflow.com/questions/2568194/populate-a-vector-with-all-multimap-values-with-a-given-key + // shorter syntax with mem_fn() + // https://stackoverflow.com/a/36775400/5257399 + transform( + lowerBound, + upperBound, + back_inserter(rows), + mem_fn(&BanksToPresets::value_type::second) +// [](BanksToPresets::value_type element){return element.second;} + ); + } + table.deselectAllRows(); table.updateContent(); table.getHeader().setSortColumnId(0, true); @@ -123,7 +175,12 @@ void TableComponent::parameterChanged(const String& parameterID, float newValue) void TableComponent::valueTreePropertyChanged( ValueTree& treeWhosePropertyHasChanged, const Identifier& property) { - if (treeWhosePropertyHasChanged.getType() == StringRef("presets")) { + // if (treeWhosePropertyHasChanged.getType() == StringRef("presets")) { + // if (property == StringRef("synthetic")) { + // loadModelFrom(treeWhosePropertyHasChanged); + // } + // } + if (treeWhosePropertyHasChanged.getType() == StringRef("banks")) { if (property == StringRef("synthetic")) { loadModelFrom(treeWhosePropertyHasChanged); } diff --git a/Source/TableComponent.h b/Source/TableComponent.h index 41feaa3..e5a914f 100644 --- a/Source/TableComponent.h +++ b/Source/TableComponent.h @@ -12,6 +12,7 @@ #include "PresetsToBanks.h" #include #include +#include using namespace std; @@ -91,7 +92,8 @@ public: inline virtual void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) override {}; inline virtual void valueTreeRedirected (ValueTree& treeWhichHasBeenChanged) override {}; private: - void loadModelFrom(ValueTree& presets); + // void loadModelFrom(ValueTree& presets); + void loadModelFrom(ValueTree& banks); void selectCurrentPreset(); AudioProcessorValueTreeState& valueTreeState; @@ -99,6 +101,9 @@ private: TableListBox table; // the table component itself Font font; + typedef multimap BanksToPresets; + BanksToPresets banksToPresets; + // vector columns; vector rows;