JUCE SDK integration.
This commit is contained in:
parent
8e09f58944
commit
adcbcdfd5e
16 changed files with 1057 additions and 0 deletions
97
examples/juce/Editor.cpp
Normal file
97
examples/juce/Editor.cpp
Normal file
|
|
@ -0,0 +1,97 @@
|
|||
#include "Editor.h"
|
||||
XtcJuceEditor::XtcJuceEditor(XtcJuceProcessor& owner)
|
||||
: AudioProcessorEditor(owner),engine(owner)
|
||||
{
|
||||
const std::array<const char*,4> ids{{"gain","cutoff","room","wet"}};
|
||||
const std::array<const char*,4> names{{"OUTPUT / dB","TONE / Hz","ROOM SIZE","REVERB MIX"}};
|
||||
for (size_t i=0;i<sliders.size();++i) {
|
||||
auto& slider=sliders[i];
|
||||
slider.setSliderStyle(juce::Slider::RotaryHorizontalVerticalDrag);
|
||||
slider.setTextBoxStyle(juce::Slider::TextBoxBelow,false,95,24);
|
||||
slider.setColour(juce::Slider::rotarySliderFillColourId,juce::Colour(0xff74dbc1));
|
||||
slider.setColour(juce::Slider::textBoxOutlineColourId,juce::Colours::transparentBlack);
|
||||
addAndMakeVisible(slider);
|
||||
labels[i].setText(names[i],juce::dontSendNotification);
|
||||
labels[i].setJustificationType(juce::Justification::centred); addAndMakeVisible(labels[i]);
|
||||
attachments[i]=std::make_unique<juce::AudioProcessorValueTreeState::SliderAttachment>(engine.parameters,ids[i],slider);
|
||||
slider.textFromValueFunction=[i](double value) { return juce::String(value,i==1 ? 0 : 2); };
|
||||
slider.updateText();
|
||||
}
|
||||
for (auto* button : {&save,&load,&panicButton}) addAndMakeVisible(*button);
|
||||
addAndMakeVisible(effects); addAndMakeVisible(status); addAndMakeVisible(keyboard);
|
||||
effectsAttachment=std::make_unique<juce::AudioProcessorValueTreeState::ButtonAttachment>(engine.parameters,"effects",effects);
|
||||
keyboardState.addListener(this);
|
||||
keyboard.setAvailableRange(36,96); keyboard.setLowestVisibleKey(48); keyboard.setKeyWidth(24);
|
||||
keyboard.setColour(juce::MidiKeyboardComponent::keyDownOverlayColourId,juce::Colour(0xff74dbc1));
|
||||
save.onClick=[this]{choosePreset(true);}; load.onClick=[this]{choosePreset(false);};
|
||||
panicButton.onClick=[this]{keyboardState.allNotesOff(0);engine.panic();};
|
||||
setSize(780,490); startTimerHz(30);
|
||||
}
|
||||
XtcJuceEditor::~XtcJuceEditor()
|
||||
{
|
||||
stopTimer(); keyboardState.removeListener(this); engine.panic();
|
||||
}
|
||||
void XtcJuceEditor::paint(juce::Graphics& graphics)
|
||||
{
|
||||
graphics.fillAll(juce::Colour(0xff101c23));
|
||||
graphics.setColour(juce::Colour(0xff74dbc1));
|
||||
graphics.setFont(juce::FontOptions(40.0f,juce::Font::bold)); graphics.drawText("xtc",24,15,100,55,juce::Justification::left);
|
||||
graphics.setColour(juce::Colour(0xffedf5f5));
|
||||
graphics.setFont(juce::FontOptions(23.0f)); graphics.drawText("Soft Keys",130,20,300,40,juce::Justification::left);
|
||||
graphics.setColour(juce::Colour(0xffa4b7c1)); graphics.setFont(juce::FontOptions(14.0f));
|
||||
graphics.drawText("Play. Shape. Explore.",132,58,420,25,juce::Justification::left);
|
||||
graphics.setColour(juce::Colour(0xff283a44)); graphics.fillRoundedRectangle(590,38,160,9,4);
|
||||
graphics.setColour(juce::Colour(0xff74dbc1)); graphics.fillRoundedRectangle(590,38,160*juce::jlimit(0.0f,1.0f,level),9,4);
|
||||
}
|
||||
void XtcJuceEditor::resized()
|
||||
{
|
||||
for (size_t i=0;i<sliders.size();++i) {
|
||||
const int x=20+static_cast<int>(i)*190;
|
||||
labels[i].setBounds(x,105,170,25); sliders[i].setBounds(x,135,170,150);
|
||||
}
|
||||
effects.setBounds(25,300,220,30); save.setBounds(380,300,120,30);
|
||||
load.setBounds(510,300,120,30); panicButton.setBounds(640,300,110,30);
|
||||
status.setBounds(25,340,725,30); keyboard.setBounds(20,385,740,85);
|
||||
}
|
||||
void XtcJuceEditor::timerCallback()
|
||||
{
|
||||
level=engine.peak(); repaint(580,30,180,25);
|
||||
const juce::String text=engine.processingFailed() ? "Audio preparation or processing failed; reopen the device to retry."
|
||||
: (engine.droppedEvents() ? "MIDI overflow: voices cleared. Reduce the event rate."
|
||||
: "Use the keyboard below or select a MIDI input in the standalone Audio/MIDI settings.");
|
||||
status.setText(presetStatus.isNotEmpty() ? presetStatus : text,juce::dontSendNotification);
|
||||
}
|
||||
void XtcJuceEditor::handleNoteOn(juce::MidiKeyboardState*,int channel,int note,float velocity)
|
||||
{ engine.enqueueNote(true,channel,note,velocity); }
|
||||
void XtcJuceEditor::handleNoteOff(juce::MidiKeyboardState*,int channel,int note,float velocity)
|
||||
{ engine.enqueueNote(false,channel,note,velocity); }
|
||||
void XtcJuceEditor::choosePreset(bool saving)
|
||||
{
|
||||
if (chooser) return;
|
||||
chooser=std::make_unique<juce::FileChooser>(saving ? "Save xtc JUCE preset" : "Load xtc JUCE preset",
|
||||
juce::File{},"*.xtcjuce");
|
||||
const int browserFlags=juce::FileBrowserComponent::canSelectFiles |
|
||||
(saving ? juce::FileBrowserComponent::saveMode | juce::FileBrowserComponent::warnAboutOverwriting
|
||||
: juce::FileBrowserComponent::openMode);
|
||||
chooser->launchAsync(browserFlags,[safe=juce::Component::SafePointer<XtcJuceEditor>(this),saving](const juce::FileChooser& dialog){
|
||||
if (!safe) return;
|
||||
const auto file=dialog.getResult();
|
||||
if (file!=juce::File{}) {
|
||||
if (saving) {
|
||||
juce::MemoryBlock state; safe->engine.getStateInformation(state);
|
||||
juce::TemporaryFile temporary(file);
|
||||
if (!temporary.getFile().replaceWithData(state.getData(),state.getSize()) ||
|
||||
!temporary.overwriteTargetFileWithTemporary())
|
||||
safe->presetStatus="Could not save preset.";
|
||||
else safe->presetStatus="Preset saved.";
|
||||
} else {
|
||||
juce::MemoryBlock state;
|
||||
if (file.getSize()>0 && file.getSize()<=65536 && file.loadFileAsData(state))
|
||||
safe->presetStatus=safe->engine.restorePreset(state.getData(),static_cast<int>(state.getSize()))
|
||||
? "Preset loaded." : "Invalid preset; current settings retained.";
|
||||
else safe->presetStatus="Could not read preset (limit 64 KiB).";
|
||||
}
|
||||
}
|
||||
safe->chooser.reset();
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue