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.
This commit is contained in:
parent
d8ce91e666
commit
0587e2f68a
|
@ -234,7 +234,7 @@ void FluidSynthModel::parameterChanged(const String& parameterID, float newValue
|
||||||
static_cast<unsigned int>(preset));
|
static_cast<unsigned int>(preset));
|
||||||
|
|
||||||
// fluid_synth_bank_select(synth.get(), channel, value);
|
// 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_t* sfont{fluid_synth_get_sfont_by_id(synth.get(), sfont_id)};
|
||||||
// fluid_sfont_iteration_start(sfont);
|
// fluid_sfont_iteration_start(sfont);
|
||||||
// fluid_preset_t* presetObj{fluid_sfont_iteration_next(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)};
|
fluid_sfont_t* sfont {fluid_synth_get_sfont_by_id(synth.get(), sfont_id)};
|
||||||
ValueTree banks{"banks"};
|
ValueTree banks{"banks"};
|
||||||
if (sfont != nullptr) {
|
if (sfont != nullptr) {
|
||||||
// int initialBankOffset{fluid_synth_get_bank_offset(synth.get(), sfont_id)};
|
int greatestEncounteredBank{-1};
|
||||||
banks.appendChild({ "bank", {
|
ValueTree bank;
|
||||||
{ "num", /* initialBankOffset */ 0 },
|
|
||||||
}, {} }, nullptr);
|
|
||||||
// int greatestPersistedBank{initialBankOffset};
|
|
||||||
int greatestPersistedBank{0};
|
|
||||||
|
|
||||||
fluid_sfont_iteration_start(sfont);
|
fluid_sfont_iteration_start(sfont);
|
||||||
|
|
||||||
for(fluid_preset_t* preset {fluid_sfont_iteration_next(sfont)};
|
for(fluid_preset_t* preset {fluid_sfont_iteration_next(sfont)};
|
||||||
preset != nullptr;
|
preset != nullptr;
|
||||||
preset = fluid_sfont_iteration_next(sfont)) {
|
preset = fluid_sfont_iteration_next(sfont)) {
|
||||||
int bank{fluid_preset_get_banknum(preset) /* + initialBankOffset */};
|
int bankNum{fluid_preset_get_banknum(preset)};
|
||||||
if (bank > greatestPersistedBank) {
|
if (bankNum > greatestEncounteredBank) {
|
||||||
banks.appendChild({ "bank", {
|
if (greatestEncounteredBank > -1) {
|
||||||
{ "num", bank },
|
banks.appendChild(bank, nullptr);
|
||||||
}, {} }, nullptr);
|
}
|
||||||
greatestPersistedBank = bank;
|
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").copyPropertiesAndChildrenFrom(banks, nullptr);
|
||||||
valueTreeState.state.getChildWithName("banks").sendPropertyChangeMessage("synthetic");
|
valueTreeState.state.getChildWithName("banks").sendPropertyChangeMessage("synthetic");
|
||||||
refreshPresets();
|
|
||||||
|
#if JUCE_DEBUG
|
||||||
|
unique_ptr<XmlElement> xml{valueTreeState.state.createXml()};
|
||||||
|
Logger::outputDebugString(xml->createDocument("",false,false));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void FluidSynthModel::refreshPresets() {
|
// void FluidSynthModel::refreshBanks() {
|
||||||
fluid_sfont_t* sfont {fluid_synth_get_sfont_by_id(synth.get(), sfont_id)};
|
// fluid_sfont_t* sfont {fluid_synth_get_sfont_by_id(synth.get(), sfont_id)};
|
||||||
ValueTree presets{"presets"};
|
// ValueTree banks{"banks"};
|
||||||
if (sfont != nullptr) {
|
// if (sfont != nullptr) {
|
||||||
RangedAudioParameter *param {valueTreeState.getParameter("bank")};
|
// // int initialBankOffset{fluid_synth_get_bank_offset(synth.get(), sfont_id)};
|
||||||
jassert(dynamic_cast<AudioParameterInt*> (param) != nullptr);
|
// banks.appendChild({ "bank", {
|
||||||
AudioParameterInt* castParam {dynamic_cast<AudioParameterInt*> (param)};
|
// { "num", /* initialBankOffset */ 0 },
|
||||||
int value{castParam->get()};
|
// }, {} }, 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)};
|
// void FluidSynthModel::refreshPresets() {
|
||||||
preset != nullptr;
|
// fluid_sfont_t* sfont {fluid_synth_get_sfont_by_id(synth.get(), sfont_id)};
|
||||||
preset = fluid_sfont_iteration_next(sfont)) {
|
// ValueTree presets{"presets"};
|
||||||
int bank{fluid_preset_get_banknum(preset) /* + initialBank */};
|
// if (sfont != nullptr) {
|
||||||
if (bank == value) {
|
// RangedAudioParameter *param {valueTreeState.getParameter("bank")};
|
||||||
presets.appendChild({ "preset", {
|
// jassert(dynamic_cast<AudioParameterInt*> (param) != nullptr);
|
||||||
{ "num", fluid_preset_get_num(preset) },
|
// AudioParameterInt* castParam {dynamic_cast<AudioParameterInt*> (param)};
|
||||||
{ "name", String{fluid_preset_get_name(preset)} }
|
// int value{castParam->get()};
|
||||||
}, {} }, nullptr);
|
|
||||||
}
|
// // int initialBank{fluid_synth_get_bank_offset(synth.get(), sfont_id)};
|
||||||
}
|
|
||||||
}
|
// fluid_sfont_iteration_start(sfont);
|
||||||
valueTreeState.state.getChildWithName("presets").copyPropertiesAndChildrenFrom(presets, nullptr);
|
|
||||||
valueTreeState.state.getChildWithName("presets").sendPropertyChangeMessage("synthetic");
|
// 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() {
|
// void FluidSynthModel::refreshBanksAndPresets() {
|
||||||
// fluid_sfont_t* sfont {fluid_synth_get_sfont_by_id(synth.get(), sfont_id)};
|
// fluid_sfont_t* sfont {fluid_synth_get_sfont_by_id(synth.get(), sfont_id)};
|
||||||
|
|
|
@ -105,7 +105,7 @@ private:
|
||||||
|
|
||||||
int handleMidiEvent(void* data, fluid_midi_event_t* event);
|
int handleMidiEvent(void* data, fluid_midi_event_t* event);
|
||||||
void refreshBanks();
|
void refreshBanks();
|
||||||
void refreshPresets();
|
// void refreshPresets();
|
||||||
// void refreshBanksAndPresets();
|
// void refreshBanksAndPresets();
|
||||||
|
|
||||||
// ValueTreeListener valueTreeListener;
|
// ValueTreeListener valueTreeListener;
|
||||||
|
|
|
@ -47,7 +47,7 @@ JuicySFAudioProcessor::JuicySFAudioProcessor()
|
||||||
{ "path", "" },
|
{ "path", "" },
|
||||||
}, {} }, nullptr);
|
}, {} }, nullptr);
|
||||||
// no properties, no subtrees (yet)
|
// no properties, no subtrees (yet)
|
||||||
valueTreeState.state.appendChild({ "presets", {}, {} }, nullptr);
|
// valueTreeState.state.appendChild({ "presets", {}, {} }, nullptr);
|
||||||
// no properties, no subtrees (yet)
|
// no properties, no subtrees (yet)
|
||||||
valueTreeState.state.appendChild({ "banks", {}, {} }, nullptr);
|
valueTreeState.state.appendChild({ "banks", {}, {} }, nullptr);
|
||||||
// valueTreeState.state.setProperty("soundFontPath", "", nullptr);
|
// valueTreeState.state.setProperty("soundFontPath", "", nullptr);
|
||||||
|
|
|
@ -8,6 +8,9 @@
|
||||||
|
|
||||||
#include "TableComponent.h"
|
#include "TableComponent.h"
|
||||||
#include "Util.h"
|
#include "Util.h"
|
||||||
|
#include <functional>
|
||||||
|
#include <iterator>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace Util;
|
using namespace Util;
|
||||||
|
@ -74,8 +77,9 @@ TableComponent::TableComponent(
|
||||||
table.setWantsKeyboardFocus(false);
|
table.setWantsKeyboardFocus(false);
|
||||||
|
|
||||||
// table.selectRow();
|
// table.selectRow();
|
||||||
ValueTree presets{valueTreeState.state.getChildWithName("presets")};
|
// ValueTree presets{valueTreeState.state.getChildWithName("presets")};
|
||||||
loadModelFrom(presets);
|
ValueTree banks{valueTreeState.state.getChildWithName("banks")};
|
||||||
|
loadModelFrom(banks);
|
||||||
// selectCurrentPreset();
|
// selectCurrentPreset();
|
||||||
|
|
||||||
// we could now change some initial settings..
|
// we could now change some initial settings..
|
||||||
|
@ -93,15 +97,63 @@ TableComponent::~TableComponent() {
|
||||||
valueTreeState.state.removeListener(this);
|
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<numChildren; i++) {
|
||||||
|
// ValueTree child{presets.getChild(i)};
|
||||||
|
// int num{child.getProperty("num")};
|
||||||
|
// String name{child.getProperty("name")};
|
||||||
|
// rows.emplace_back(num, name);
|
||||||
|
// }
|
||||||
|
// table.deselectAllRows();
|
||||||
|
// table.updateContent();
|
||||||
|
// table.getHeader().setSortColumnId(0, true);
|
||||||
|
// selectCurrentPreset();
|
||||||
|
// table.repaint();
|
||||||
|
// }
|
||||||
|
|
||||||
|
void TableComponent::loadModelFrom(ValueTree& banks) {
|
||||||
rows.clear();
|
rows.clear();
|
||||||
int numChildren{presets.getNumChildren()};
|
banksToPresets.clear();
|
||||||
for(int i{0}; i<numChildren; i++) {
|
int banksChildren{banks.getNumChildren()};
|
||||||
ValueTree child{presets.getChild(i)};
|
for(int bankIx{0}; bankIx<banksChildren; bankIx++) {
|
||||||
int num{child.getProperty("num")};
|
// vector<TableRow> presets;
|
||||||
String name{child.getProperty("name")};
|
ValueTree bank{banks.getChild(bankIx)};
|
||||||
rows.emplace_back(num, name);
|
int bankNum{bank.getProperty("num")};
|
||||||
|
int bankChildren{bank.getNumChildren()};
|
||||||
|
for(int presetIx{0}; presetIx<bankChildren; presetIx++) {
|
||||||
|
ValueTree preset{bank.getChild(presetIx)};
|
||||||
|
int presetNum{preset.getProperty("num")};
|
||||||
|
String presetName{preset.getProperty("name")};
|
||||||
|
// presets.emplace_back(presetNum, presetName);
|
||||||
|
TableRow row{presetNum, move(presetName)};
|
||||||
|
// banksToPresets.insert(BanksToPresets::value_type(bankNum, move(row)));
|
||||||
|
banksToPresets.emplace(bankNum, move(row));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
RangedAudioParameter *param{valueTreeState.getParameter("bank")};
|
||||||
|
jassert(dynamic_cast<AudioParameterInt*>(param) != nullptr);
|
||||||
|
AudioParameterInt* castParam{dynamic_cast<AudioParameterInt*>(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.deselectAllRows();
|
||||||
table.updateContent();
|
table.updateContent();
|
||||||
table.getHeader().setSortColumnId(0, true);
|
table.getHeader().setSortColumnId(0, true);
|
||||||
|
@ -123,7 +175,12 @@ void TableComponent::parameterChanged(const String& parameterID, float newValue)
|
||||||
void TableComponent::valueTreePropertyChanged(
|
void TableComponent::valueTreePropertyChanged(
|
||||||
ValueTree& treeWhosePropertyHasChanged,
|
ValueTree& treeWhosePropertyHasChanged,
|
||||||
const Identifier& property) {
|
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")) {
|
if (property == StringRef("synthetic")) {
|
||||||
loadModelFrom(treeWhosePropertyHasChanged);
|
loadModelFrom(treeWhosePropertyHasChanged);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "PresetsToBanks.h"
|
#include "PresetsToBanks.h"
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
@ -91,7 +92,8 @@ public:
|
||||||
inline virtual void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) override {};
|
inline virtual void valueTreeParentChanged (ValueTree& treeWhoseParentHasChanged) override {};
|
||||||
inline virtual void valueTreeRedirected (ValueTree& treeWhichHasBeenChanged) override {};
|
inline virtual void valueTreeRedirected (ValueTree& treeWhichHasBeenChanged) override {};
|
||||||
private:
|
private:
|
||||||
void loadModelFrom(ValueTree& presets);
|
// void loadModelFrom(ValueTree& presets);
|
||||||
|
void loadModelFrom(ValueTree& banks);
|
||||||
void selectCurrentPreset();
|
void selectCurrentPreset();
|
||||||
|
|
||||||
AudioProcessorValueTreeState& valueTreeState;
|
AudioProcessorValueTreeState& valueTreeState;
|
||||||
|
@ -99,6 +101,9 @@ private:
|
||||||
TableListBox table; // the table component itself
|
TableListBox table; // the table component itself
|
||||||
Font font;
|
Font font;
|
||||||
|
|
||||||
|
typedef multimap<int, TableRow> BanksToPresets;
|
||||||
|
BanksToPresets banksToPresets;
|
||||||
|
|
||||||
// vector<string> columns;
|
// vector<string> columns;
|
||||||
vector<TableRow> rows;
|
vector<TableRow> rows;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user