decoupling achieved. compiles. doesn't immediately explode. but neither banks nor presets visible.

This commit is contained in:
Alex Birch 2019-07-14 17:22:36 +01:00
parent 58574425f3
commit 8c1be957fe
No known key found for this signature in database
GPG Key ID: 305EB1F98D44ACBA
9 changed files with 183 additions and 146 deletions

View File

@ -7,8 +7,8 @@
#include "Util.h" #include "Util.h"
FilePicker::FilePicker( FilePicker::FilePicker(
AudioProcessorValueTreeState& valueTreeState, AudioProcessorValueTreeState& valueTreeState
FluidSynthModel& fluidSynthModel // FluidSynthModel& fluidSynthModel
) )
: fileChooser{ : fileChooser{
"File", "File",
@ -20,7 +20,7 @@ FilePicker::FilePicker(
String(), String(),
"Choose a Soundfont file to load into the synthesizer"} "Choose a Soundfont file to load into the synthesizer"}
, valueTreeState{valueTreeState} , valueTreeState{valueTreeState}
, fluidSynthModel{fluidSynthModel} // , fluidSynthModel{fluidSynthModel}
// , currentPath{} // , currentPath{}
{ {
// faster (rounded edges introduce transparency) // faster (rounded edges introduce transparency)

View File

@ -15,8 +15,8 @@ class FilePicker: public Component,
{ {
public: public:
FilePicker( FilePicker(
AudioProcessorValueTreeState& valueTreeState, AudioProcessorValueTreeState& valueTreeState
FluidSynthModel& fluidSynthModel // FluidSynthModel& fluidSynthModel
); );
~FilePicker(); ~FilePicker();
@ -41,7 +41,7 @@ private:
FilenameComponent fileChooser; FilenameComponent fileChooser;
AudioProcessorValueTreeState& valueTreeState; AudioProcessorValueTreeState& valueTreeState;
FluidSynthModel& fluidSynthModel; // FluidSynthModel& fluidSynthModel;
String currentPath; String currentPath;

View File

@ -4,6 +4,7 @@
#include "Pills.h" #include "Pills.h"
#include "MyColours.h" #include "MyColours.h"
#include <algorithm>
using namespace std; using namespace std;
@ -14,7 +15,8 @@ Pill::Pill(
bool isLast bool isLast
) )
// : pills{pills} // : pills{pills}
: bank{bank} : valueTreeState{valueTreeState}
, bank{bank}
, textButton{String(bank)} , textButton{String(bank)}
{ {
textButton.setConnectedEdges ( textButton.setConnectedEdges (
@ -25,16 +27,18 @@ Pill::Pill(
loadToggleState(); loadToggleState();
textButton.setClickingTogglesState(true); textButton.setClickingTogglesState(true);
valueTreeState.state.addListener(this); valueTreeState.addParameterListener("bank", this);
// valueTreeState.state.addListener(this);
textButton.addListener(this); textButton.addListener(this);
} }
Pill::~Pill() { Pill::~Pill() {
valueTreeState.state.removeListener(this); valueTreeState.removeParameterListener("bank", this);
// valueTreeState.state.removeListener(this);
textButton.removeListener(this); textButton.removeListener(this);
} }
Pill::loadToggleState() { void Pill::loadToggleState() {
RangedAudioParameter *param {valueTreeState.getParameter("bank")}; RangedAudioParameter *param {valueTreeState.getParameter("bank")};
jassert(dynamic_cast<AudioParameterInt*> (param) != nullptr); jassert(dynamic_cast<AudioParameterInt*> (param) != nullptr);
AudioParameterInt* castParam {dynamic_cast<AudioParameterInt*> (param)}; AudioParameterInt* castParam {dynamic_cast<AudioParameterInt*> (param)};
@ -57,13 +61,13 @@ void Pill::parameterChanged(const String& parameterID, float newValue) {
} }
} }
void Pill::valueTreePropertyChanged( // void Pill::valueTreePropertyChanged(
ValueTree& treeWhosePropertyHasChanged, // ValueTree& treeWhosePropertyHasChanged,
const Identifier& property) { // const Identifier& property) {
if (treeWhosePropertyHasChanged.getType() == StringRef("presets")) { // if (treeWhosePropertyHasChanged.getType() == StringRef("presets")) {
loadModelFrom(treeWhosePropertyHasChanged); // loadModelFrom(treeWhosePropertyHasChanged);
} // }
} // }
Pills::Pills( Pills::Pills(
AudioProcessorValueTreeState& valueTreeState AudioProcessorValueTreeState& valueTreeState
@ -83,7 +87,8 @@ Pills::Pills(
setOpaque (true); setOpaque (true);
// populate(initiallySelectedItem); // populate(initiallySelectedItem);
loadModelFrom(valueTreeState.state.getChildWithName("banks")); ValueTree banks{valueTreeState.state.getChildWithName("banks")};
loadModelFrom(banks);
valueTreeState.state.addListener(this); valueTreeState.state.addListener(this);
} }
@ -109,11 +114,12 @@ void Pills::loadModelFrom(ValueTree& banks) {
// rows.push_back(unique_ptr<Pill>(new Pill(), [](Pill* pill) { // rows.push_back(unique_ptr<Pill>(new Pill(), [](Pill* pill) {
// pill->remo // pill->remo
// })); // }));
pills.emplace_back( pills.push_back(
this.valueTreeState, make_unique<Pill>(
valueTreeState,
num, num,
i == 0, i == 0,
i == numChildren - 1); i == numChildren - 1));
} }
} }
@ -160,21 +166,51 @@ void Pills::loadModelFrom(ValueTree& banks) {
// } // }
void Pills::cycle(bool right) { void Pills::cycle(bool right) {
// TODO: base this on valueTree RangedAudioParameter *param {valueTreeState.getParameter("bank")};
int currentIx = static_cast<const int>(distance(pills.begin(), find(pills.begin(), pills.end(), selected))); jassert(dynamic_cast<AudioParameterInt*> (param) != nullptr);
AudioParameterInt* castParam {dynamic_cast<AudioParameterInt*> (param)};
int currentlySelectedBank{castParam->get()};
ValueTree banks{valueTreeState.state.getChildWithName("banks")};
// int numChildren{banks.getNumChildren()};
vector<int> bankInts;
bankInts.resize(banks.getNumChildren());
transform(banks.begin(), banks.end(), bankInts.begin(), [](ValueTree bank) -> int {
return bank.getProperty("num");
});
// int closestBank{currentlySelectedBank};
// for(int i{0}; i < numChildren; i++) {
// ValueTree child{banks.getChild(i)};
// int proposedBank{child.getProperty("num")};
// if (right && proposedBank > currentlySelectedBank) {
// closestBank = jmin(closestBank, proposedBank);
// } else if (left )
// }
int currentIx{static_cast<const int>(distance(bankInts.begin(), find(bankInts.begin(), bankInts.end(), currentlySelectedBank)))};
currentIx += right ? 1 : pills.size()-1; currentIx += right ? 1 : pills.size()-1;
pills[currentIx % pills.size()]->textButton.triggerClick(); // pills[currentIx % pills.size()]->textButton.triggerClick();
*castParam = bankInts[currentIx % bankInts.size()];
// TODO: base this on valueTree
// int currentIx = static_cast<const int>(distance(pills.begin(), find(pills.begin(), pills.end(), selected)));
// currentIx += right ? 1 : pills.size()-1;
// pills[currentIx % pills.size()]->textButton.triggerClick();
} }
void Pills::resized() { void Pills::resized() {
int index = 0; int index = 0;
Rectangle<int> r (getLocalBounds()); Rectangle<int> r (getLocalBounds());
const int equalWidth = r.proportionOfWidth(buttons.size() <= 0 ? 1.0 : 1.0f/buttons.size()); const int equalWidth = r.proportionOfWidth(pills.size() <= 0 ? 1.0 : 1.0f/pills.size());
for(TextButton* t : buttons) { for(auto& pill : pills) {
Rectangle<int> r2 (getLocalBounds()); Rectangle<int> r2 (getLocalBounds());
r2.removeFromLeft(equalWidth * index); r2.removeFromLeft(equalWidth * index);
r2.removeFromRight(equalWidth * (buttons.size()-index-1)); r2.removeFromRight(equalWidth * (static_cast<int>(pills.size())-index-1));
t->setBounds (r2); pill->textButton.setBounds (r2);
index++; index++;
} }
} }
@ -185,4 +221,4 @@ void Pills::resized() {
void Pills::paint(Graphics& g) void Pills::paint(Graphics& g)
{ {
g.fillAll(MyColours::getUIColourIfAvailable(LookAndFeel_V4::ColourScheme::UIColour::windowBackground, Colours::lightgrey)); g.fillAll(MyColours::getUIColourIfAvailable(LookAndFeel_V4::ColourScheme::UIColour::windowBackground, Colours::lightgrey));
} }

View File

@ -32,8 +32,7 @@ private:
TextButton textButton; TextButton textButton;
friend class Pills; friend class Pills;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pill) };
}
class Pills class Pills
: public Component : public Component
@ -89,4 +88,4 @@ private:
void paint(Graphics& g) override; void paint(Graphics& g) override;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pills) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Pills)
}; };

View File

@ -21,8 +21,8 @@ JuicySFAudioProcessorEditor::JuicySFAudioProcessorEditor(
, valueTreeState{valueTreeState} , valueTreeState{valueTreeState}
// sharedParams{p.getSharedParams()}, // sharedParams{p.getSharedParams()},
, midiKeyboard{p.keyboardState, SurjectiveMidiKeyboardComponent::horizontalKeyboard} , midiKeyboard{p.keyboardState, SurjectiveMidiKeyboardComponent::horizontalKeyboard}
, tablesComponent{valueTreeState, p.getFluidSynthModel()} , tablesComponent{valueTreeState}
, filePicker{valueTreeState, p.getFluidSynthModel()} , filePicker{valueTreeState}
, slidersComponent{valueTreeState, p.getFluidSynthModel()} , slidersComponent{valueTreeState, p.getFluidSynthModel()}
{ {
// set resize limits for this plug-in // set resize limits for this plug-in

View File

@ -17,7 +17,7 @@ using namespace Util;
This class shows how to implement a TableListBoxModel to show in a TableListBox. This class shows how to implement a TableListBoxModel to show in a TableListBox.
*/ */
TableComponent::TableComponent( TableComponent::TableComponent(
AudioProcessorValueTreeState& valueTreeState, AudioProcessorValueTreeState& valueTreeState
// const vector<string> &columns, // const vector<string> &columns,
// const vector<TableRow> &rows, // const vector<TableRow> &rows,
// const function<void (int)> &onRowSelected, // const function<void (int)> &onRowSelected,
@ -74,7 +74,8 @@ TableComponent::TableComponent(
table.setWantsKeyboardFocus(false); table.setWantsKeyboardFocus(false);
// table.selectRow(); // table.selectRow();
loadModelFrom(valueTreeState.state.getChildWithName("presets")); ValueTree presets{valueTreeState.state.getChildWithName("presets")};
loadModelFrom(presets);
// selectCurrentPreset(); // selectCurrentPreset();
// we could now change some initial settings.. // we could now change some initial settings..
@ -160,9 +161,9 @@ void TableComponent::paintRowBackground (
String TableRow::getStringContents(int columnId) { String TableRow::getStringContents(int columnId) {
if (columnId <= 1) { if (columnId <= 1) {
return String(row.preset); return String(preset);
} }
return row.name; return name;
} }
// This is overloaded from TableListBoxModel, and must paint any cells that aren't using custom // This is overloaded from TableListBoxModel, and must paint any cells that aren't using custom

View File

@ -29,7 +29,6 @@ private:
String name; String name;
friend class TableComponent; friend class TableComponent;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TableRow)
}; };

View File

@ -8,105 +8,107 @@ using namespace std;
using namespace placeholders; using namespace placeholders;
TablesComponent::TablesComponent( TablesComponent::TablesComponent(
AudioProcessorValueTreeState& valueTreeState, AudioProcessorValueTreeState& valueTreeState
FluidSynthModel& fluidSynthModel // FluidSynthModel& fluidSynthModel
) )
: valueTreeState{valueTreeState} : valueTreeState{valueTreeState}
, fluidSynthModel{fluidSynthModel} // , fluidSynthModel{fluidSynthModel}
, banksToPresets{fluidSynthModel.getBanks()} , banks{valueTreeState}
, initialised{false} , presetTable{valueTreeState}
// , banksToPresets{fluidSynthModel.getBanks()}
// , initialised{false}
{ {
fluid_preset_t* currentPreset = getCurrentPreset(); // fluid_preset_t* currentPreset = getCurrentPreset();
selectedBank = -1; // selectedBank = -1;
int selectedPreset = -1; // int selectedPreset = -1;
if (currentPreset != nullptr) { // if (currentPreset != nullptr) {
selectedBank = fluid_preset_get_banknum(currentPreset); // selectedBank = fluid_preset_get_banknum(currentPreset);
selectedPreset = fluid_preset_get_num(currentPreset); // selectedPreset = fluid_preset_get_num(currentPreset);
} // }
// auto rowToPresetMapper = [this](const vector<string> &row) { // auto rowToPresetMapper = [this](const vector<string> &row) {
// return stoi(row[0]); // return stoi(row[0]);
// }; // };
auto itemToBankMapper = [](const string &item) { // auto itemToBankMapper = [](const string &item) {
return stoi(item); // return stoi(item);
}; // };
presetTable = new TableComponent( // presetTable = new TableComponent(
valueTreeState, // valueTreeState,
// {"#", "Name"}, // // {"#", "Name"},
// mapPresets( // // mapPresets(
// banksToPresets, // // banksToPresets,
// selectedBank // // selectedBank
// ), // // ),
// [this](int preset){ // // [this](int preset){
// this->onPresetSelected(preset); // // this->onPresetSelected(preset);
// }, // // },
// rowToPresetMapper, // // rowToPresetMapper,
// presetToIndexMapper(selectedPreset) // // presetToIndexMapper(selectedPreset)
); // );
banks = new Pills( // banks = new Pills(
"Banks", // "Banks",
mapBanks(banksToPresets), // mapBanks(banksToPresets),
[this](int bank){ // [this](int bank){
this->onBankSelected(bank); // this->onBankSelected(bank);
}, // },
itemToBankMapper, // itemToBankMapper,
selectedBank // selectedBank
); // );
presetTable->setWantsKeyboardFocus(false); presetTable.setWantsKeyboardFocus(false);
addAndMakeVisible(presetTable); addAndMakeVisible(presetTable);
addAndMakeVisible(banks); addAndMakeVisible(banks);
initialised = true; // initialised = true;
fluidSynthModel.addListener(this); // fluidSynthModel.addListener(this);
} }
fluid_preset_t* TablesComponent::getCurrentPreset() { // fluid_preset_t* TablesComponent::getCurrentPreset() {
shared_ptr<fluid_synth_t> synth {fluidSynthModel.getSynth()}; // shared_ptr<fluid_synth_t> synth {fluidSynthModel.getSynth()};
return fluid_synth_get_channel_preset(synth.get(), fluidSynthModel.getChannel()); // return fluid_synth_get_channel_preset(synth.get(), fluidSynthModel.getChannel());
} // }
Preset TablesComponent::getFirstPresetInBank(int bank) { // Preset TablesComponent::getFirstPresetInBank(int bank) {
pair<BanksToPresets::const_iterator, BanksToPresets::const_iterator> iterators = banksToPresets.equal_range(bank); // pair<BanksToPresets::const_iterator, BanksToPresets::const_iterator> iterators = banksToPresets.equal_range(bank);
BanksToPresets::const_iterator it = iterators.first; // BanksToPresets::const_iterator it = iterators.first;
return it->second; // return it->second;
} // }
void TablesComponent::onBankSelected(int bank) { // void TablesComponent::onBankSelected(int bank) {
if (!initialised || bank == -1) { // if (!initialised || bank == -1) {
return; // return;
} // }
cout << "Bank " << bank << endl; // cout << "Bank " << bank << endl;
selectedBank = bank; // selectedBank = bank;
Preset firstPresetInBank = getFirstPresetInBank(bank); // Preset firstPresetInBank = getFirstPresetInBank(bank);
presetTable->setRows( // presetTable->setRows(
mapPresets( // mapPresets(
banksToPresets, // banksToPresets,
bank // bank
), // ),
presetToIndexMapper(firstPresetInBank.getPreset()) // presetToIndexMapper(firstPresetInBank.getPreset())
); // );
} // }
int TablesComponent::presetToIndexMapper(int preset) { // int TablesComponent::presetToIndexMapper(int preset) {
int ix = 0; // int ix = 0;
pair<BanksToPresets::const_iterator, BanksToPresets::const_iterator> iterators = this->banksToPresets.equal_range(this->selectedBank); // pair<BanksToPresets::const_iterator, BanksToPresets::const_iterator> iterators = this->banksToPresets.equal_range(this->selectedBank);
for (auto it = iterators.first; it != iterators.second; ++it, ix++) { // for (auto it = iterators.first; it != iterators.second; ++it, ix++) {
Preset b = it->second; // Preset b = it->second;
if (preset == b.getPreset()) { // if (preset == b.getPreset()) {
return ix; // return ix;
} // }
} // }
return 0; // return 0;
} // }
// void TablesComponent::onPresetSelected(int preset) { // void TablesComponent::onPresetSelected(int preset) {
// if (!initialised || preset == -1) { // if (!initialised || preset == -1) {
@ -117,25 +119,25 @@ int TablesComponent::presetToIndexMapper(int preset) {
// fluidSynthModel.changePreset(selectedBank, preset); // fluidSynthModel.changePreset(selectedBank, preset);
// } // }
TablesComponent::~TablesComponent() { // TablesComponent::~TablesComponent() {
delete presetTable; // delete presetTable;
delete banks; // delete banks;
// fluidSynthModel.removeListener(this); // // fluidSynthModel.removeListener(this);
} // }
vector<string> TablesComponent::mapBanks(const BanksToPresets &banksToPresets) { // vector<string> TablesComponent::mapBanks(const BanksToPresets &banksToPresets) {
vector<string> rows; // vector<string> rows;
const auto compareKey = [](const BanksToPresets::value_type& lhs, const BanksToPresets::value_type& rhs) { // const auto compareKey = [](const BanksToPresets::value_type& lhs, const BanksToPresets::value_type& rhs) {
return lhs.first < rhs.first; // return lhs.first < rhs.first;
}; // };
for(auto i = banksToPresets.begin(); i != banksToPresets.end(); i = std::upper_bound(i, banksToPresets.end(), *i, compareKey)) { // for(auto i = banksToPresets.begin(); i != banksToPresets.end(); i = std::upper_bound(i, banksToPresets.end(), *i, compareKey)) {
rows.push_back(to_string(i->first)); // rows.push_back(to_string(i->first));
} // }
return rows; // return rows;
} // }
// vector<vector<string>> TablesComponent::mapPresets(const BanksToPresets &banksToPresets, int bank) { // vector<vector<string>> TablesComponent::mapPresets(const BanksToPresets &banksToPresets, int bank) {
@ -156,18 +158,18 @@ vector<string> TablesComponent::mapBanks(const BanksToPresets &banksToPresets) {
void TablesComponent::resized() { void TablesComponent::resized() {
Rectangle<int> r (getLocalBounds()); Rectangle<int> r (getLocalBounds());
banks->setBounds (r.removeFromTop(27).reduced(5,0)); banks.setBounds (r.removeFromTop(27).reduced(5,0));
presetTable->setBounds (r); presetTable.setBounds (r);
} }
bool TablesComponent::keyPressed(const KeyPress &key) { bool TablesComponent::keyPressed(const KeyPress &key) {
if (key.getKeyCode() == KeyPress::leftKey if (key.getKeyCode() == KeyPress::leftKey
|| key.getKeyCode() == KeyPress::rightKey) { || key.getKeyCode() == KeyPress::rightKey) {
banks->cycle(key.getKeyCode() == KeyPress::rightKey); banks.cycle(key.getKeyCode() == KeyPress::rightKey);
return true; return true;
} }
return presetTable->keyPressed(key); return presetTable.keyPressed(key);
} }
// void TablesComponent::fontChanged(FluidSynthModel *, const String &) { // void TablesComponent::fontChanged(FluidSynthModel *, const String &) {

View File

@ -20,10 +20,10 @@ class TablesComponent : public Component/*,
{ {
public: public:
TablesComponent( TablesComponent(
AudioProcessorValueTreeState& valueTreeState, AudioProcessorValueTreeState& valueTreeState
FluidSynthModel& fluidSynthModel // FluidSynthModel& fluidSynthModel
); );
~TablesComponent(); // ~TablesComponent();
void resized() override; void resized() override;
@ -32,25 +32,25 @@ public:
private: private:
AudioProcessorValueTreeState& valueTreeState; AudioProcessorValueTreeState& valueTreeState;
FluidSynthModel& fluidSynthModel; // FluidSynthModel& fluidSynthModel;
int selectedBank; // int selectedBank;
Pills banks; Pills banks;
TableComponent presetTable; TableComponent presetTable;
BanksToPresets banksToPresets; // BanksToPresets banksToPresets;
// static vector<vector<string>> mapPresets(const BanksToPresets &banksToPresets, int bank); // static vector<vector<string>> mapPresets(const BanksToPresets &banksToPresets, int bank);
static vector<string> mapBanks(const BanksToPresets &banksToPresets); // static vector<string> mapBanks(const BanksToPresets &banksToPresets);
void onBankSelected(int bank); // void onBankSelected(int bank);
void onPresetSelected(int preset); // void onPresetSelected(int preset);
int presetToIndexMapper(int preset); // int presetToIndexMapper(int preset);
fluid_preset_t* getCurrentPreset(); // fluid_preset_t* getCurrentPreset();
Preset getFirstPresetInBank(int bank); // Preset getFirstPresetInBank(int bank);
bool initialised; // bool initialised;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TablesComponent) JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TablesComponent)
}; };