2
0
Fork 0
OB-Xd/Source/PluginEditor.cpp
George Reales 5d736e72cc Fixes
Preliminary Themes XML fixing knob sizes and alignments.
Fixed Preset Bar drop down menu screen misplacement.
Fixed screen flickr on preset change on Windows OS.
Updated themes folder error dialog and window size.
Fixed Menu > Manual not loading or found.
2021-09-04 22:16:50 +02:00

1442 lines
53 KiB
C++
Executable file

/*
==============================================================================
This file was auto-generated by the Introjucer!
It contains the basic startup code for a Juce application.
==============================================================================
*/
#include "PluginProcessor.h"
#include "PluginEditor.h"
#include <utility>
#include "Gui/ImageButton.h"
// #include "GUI/BinaryData.h"
#include "Utils.h"
//==============================================================================
ObxdAudioProcessorEditor::ObxdAudioProcessorEditor (ObxdAudioProcessor& ownerFilter)
: AudioProcessorEditor (&ownerFilter), ScalableComponent(&ownerFilter), processor (ownerFilter),
skinFolder (processor.getSkinFolder()),
progStart (3000),
bankStart (2000),
skinStart (1000),
skins (processor.getSkinFiles()),
banks (processor.getBankFiles())
{
LookAndFeel& lf = getLookAndFeel();
// Popup Menu Look and Feel
lf.setColour(PopupMenu::backgroundColourId, Colour(20, 20, 20));
lf.setColour(PopupMenu::textColourId, Colour(245, 245, 245));
lf.setColour(PopupMenu::highlightedBackgroundColourId, Colour(60, 60, 60));
//skinFolder = ownerFilter.getCurrentSkinFolder(); // initialized above
commandManager.registerAllCommandsForTarget(this);
commandManager.setFirstCommandTarget(this);
// reset KeyPressMappingSet
commandManager.getKeyMappings()->resetToDefaultMappings();
// having set up the default key-mappings, you might now want to load the last set
// of mappings that the user configured.
//commandManager.getKeyMappings()->restoreFromXml(lastSavedKeyMappingsXML);
// Now tell our top-level window to send any keypresses that arrive to the
// KeyPressMappingSet, which will use them to invoke the appropriate commands.
//addKeyListener(commandManager.getKeyMappings());
getTopLevelComponent()->addKeyListener (commandManager.getKeyMappings());
//Timer::callAfterDelay (100, [this] { this->grabKeyboardFocus(); }); // ensure that key presses are sent to the KeyPressTarget object
startTimer(100); // This will fix the issue
DBG("W: " <<getWidth() << " H:" << getHeight());
loadSkin (processor);
updateFromHost();
switch(processor.gui_size)
{
case 1:
ScalableComponent::setScaleFactor(1.0f, isHighResolutionDisplay());
break;
case 2:
ScalableComponent::setScaleFactor(1.5f, isHighResolutionDisplay());
break;
case 4:
ScalableComponent::setScaleFactor(2.0f, isHighResolutionDisplay());
break;
}
scaleFactorChanged();
//repaint();
}
void ObxdAudioProcessorEditor::resized() {
if (setPresetNameWindow != nullptr )
{
if (auto wrapper = dynamic_cast<ObxdAudioProcessorEditor*>(processor.getActiveEditor()))
{
auto w = proportionOfWidth(0.25f);
auto h = proportionOfHeight(0.3f);
auto x = proportionOfWidth(0.5f) - (w / 2);
auto y = wrapper->getY();
if (setPresetNameWindow != nullptr)
{
y += proportionOfHeight(0.15f);
setPresetNameWindow->setBounds(x, y, w, h);
}
}
}
skinFolder = processor.getCurrentSkinFolder();
File coords = skinFolder.getChildFile ("coords.xml");
if (!coords.existsAsFile()) {
return;
}
XmlDocument skin (coords);
auto doc = skin.getDocumentElement();
if (doc){
//int xScreen = getWidth(), yScreen = getHeight();
if (doc->getTagName() == "PROPERTIES"){
forEachXmlChildElementWithTagName(*doc, child, "VALUE"){
if (child->hasAttribute("NAME") && child->hasAttribute("x") && child->hasAttribute("y")) {
String name = child->getStringAttribute("NAME");
int x = child->getIntAttribute("x");
int y = child->getIntAttribute("y");
int d = child->getIntAttribute("d");
int w = child->getIntAttribute("w");
int h = child->getIntAttribute("h");
DBG(" COmponent : " << name);
if (mappingComps[name] != nullptr){
if (dynamic_cast<Knob*>(mappingComps[name])){
mappingComps[name]->setBounds(transformBounds(x, y, d,d));
}
else if (dynamic_cast<ButtonList*>(mappingComps[name])){
mappingComps[name]->setBounds(transformBounds(x, y, w, h));
}
else if (dynamic_cast<TooglableButton*>(mappingComps[name])){
mappingComps[name]->setBounds(transformBounds(x, y, w, h));
}
else if (dynamic_cast<ImageMenu*>(mappingComps[name])){
mappingComps[name]->setBounds(transformBounds(x, y, d, d));
}
else if (dynamic_cast<ImageButton*>(mappingComps[name])){
mappingComps[name]->setBounds(transformBounds(x, y, w, h));
}
}
}
}
}
}
}
void ObxdAudioProcessorEditor::loadSkin (ObxdAudioProcessor& ownerFilter)
{
knobAttachments.clear();
buttonListAttachments.clear();
toggleAttachments.clear();
imageButtons.clear();
popupMenus.clear();
mappingComps.clear();
ownerFilter.removeChangeListener (this);
skinFolder = ownerFilter.getCurrentSkinFolder();
File coords = skinFolder.getChildFile ("coords.xml");
bool useClassicSkin = coords.existsAsFile();
if (!useClassicSkin) {
addMenuButton (14, 25, 20, "menu");
rebuildComponents (processor);
return;
}
//if (coords.createInputStream())
XmlDocument skin (coords);
auto doc = skin.getDocumentElement();
if (!doc) {
notLoadSkin = true;
setSize (1440, 450);
}
else {
int xScreen = getWidth(), yScreen = getHeight();
if (doc->getTagName() == "PROPERTIES"){
forEachXmlChildElementWithTagName(*doc, child, "VALUE"){
if (child->hasAttribute("NAME") && child->hasAttribute("x") && child->hasAttribute("y")) {
String name = child->getStringAttribute("NAME");
int x = child->getIntAttribute("x");
int y = child->getIntAttribute("y");
int d = child->getIntAttribute("d");
int w = child->getIntAttribute("w");
int h = child->getIntAttribute("h");
if (name == "resonanceKnob"){
resonanceKnob = addKnob (x, y, d, ownerFilter, RESONANCE, "Resonance", 0);
mappingComps["resonanceKnob"] = resonanceKnob;
}
if (name == "cutoffKnob"){
cutoffKnob = addKnob (x, y, d, ownerFilter, CUTOFF, "Cutoff", 0.4);
mappingComps["cutoffKnob"] = cutoffKnob;
}
if (name == "filterEnvelopeAmtKnob"){
filterEnvelopeAmtKnob = addKnob (x, y, d, ownerFilter, ENVELOPE_AMT, "Envelope", 0);
mappingComps["filterEnvelopeAmtKnob"] = filterEnvelopeAmtKnob;
}
if (name == "multimodeKnob"){
multimodeKnob = addKnob (x, y, d, ownerFilter, MULTIMODE, "Multimode", 0.5);
mappingComps["multimodeKnob"] = multimodeKnob;
}
if (name == "volumeKnob"){
volumeKnob = addKnob (x, y, d, ownerFilter, VOLUME, "Volume", 0.4);
mappingComps["volumeKnob"] = volumeKnob;
}
if (name == "portamentoKnob"){
portamentoKnob = addKnob (x, y, d, ownerFilter, PORTAMENTO, "Portamento", 0);
mappingComps["portamentoKnob"] = portamentoKnob;
}
if (name == "osc1PitchKnob"){
osc1PitchKnob = addKnob (x, y, d, ownerFilter, OSC1P, "Osc1Pitch", 0);
mappingComps["osc1PitchKnob"] = osc1PitchKnob;
}
if (name == "pulseWidthKnob"){
pulseWidthKnob = addKnob (x, y, d, ownerFilter, PW, "PW", 0);
mappingComps["pulseWidthKnob"] = pulseWidthKnob;
}
if (name == "osc2PitchKnob"){
osc2PitchKnob = addKnob (x, y, d, ownerFilter, OSC2P, "Osc2Pitch", 0);
mappingComps["osc2PitchKnob"] = osc2PitchKnob;
}
if (name == "osc1MixKnob"){
osc1MixKnob = addKnob (x, y, d, ownerFilter, OSC1MIX, "Osc1", 1);
mappingComps["osc1MixKnob"] = osc1MixKnob;
}
if (name == "osc2MixKnob"){
osc2MixKnob = addKnob (x, y, d, ownerFilter, OSC2MIX, "Osc2", 1);
mappingComps["osc2MixKnob"] = osc2MixKnob;
}
if (name == "noiseMixKnob"){
noiseMixKnob = addKnob (x, y, d, ownerFilter, NOISEMIX, "Noise", 0);
mappingComps["noiseMixKnob"] = noiseMixKnob;
}
if (name == "xmodKnob"){
xmodKnob = addKnob (x, y, d, ownerFilter, XMOD, "Xmod", 0);
mappingComps["xmodKnob"] = xmodKnob;
}
if (name == "osc2DetuneKnob"){
osc2DetuneKnob = addKnob (x, y, d, ownerFilter, OSC2_DET, "Detune", 0);
mappingComps["osc2DetuneKnob"] = osc2DetuneKnob;
}
if (name == "envPitchModKnob"){
envPitchModKnob = addKnob (x, y, d, ownerFilter, ENVPITCH, "PEnv", 0);
mappingComps["envPitchModKnob"] = envPitchModKnob;
}
if (name == "brightnessKnob"){
brightnessKnob = addKnob (x, y, d, ownerFilter, BRIGHTNESS, "Bri", 1);
mappingComps["brightnessKnob"] = brightnessKnob;
}
if (name == "attackKnob"){
attackKnob = addKnob (x, y, d, ownerFilter, LATK, "Atk", 0);
mappingComps["attackKnob"] = attackKnob;
}
if (name == "decayKnob"){ decayKnob = addKnob (x, y, d, ownerFilter, LDEC, "Dec", 0);
mappingComps["decayKnob"] = decayKnob;
}
if (name == "sustainKnob"){
sustainKnob = addKnob (x, y, d, ownerFilter, LSUS, "Sus", 1);
mappingComps["sustainKnob"] = sustainKnob;
}
if (name == "releaseKnob"){
releaseKnob = addKnob (x, y, d, ownerFilter, LREL, "Rel", 0);
mappingComps["releaseKnob"] = releaseKnob;
}
if (name == "fattackKnob"){
fattackKnob = addKnob (x, y, d, ownerFilter, FATK, "Atk", 0);
mappingComps["fattackKnob"] = fattackKnob;
}
if (name == "fdecayKnob"){
fdecayKnob = addKnob (x, y, d, ownerFilter, FDEC, "Dec", 0);
mappingComps["fdecayKnob"] = fdecayKnob;
}
if (name == "fsustainKnob"){
fsustainKnob = addKnob (x, y, d, ownerFilter, FSUS, "Sus", 1);
mappingComps["fsustainKnob"] = fsustainKnob;
}
if (name == "freleaseKnob"){
freleaseKnob = addKnob (x, y, d, ownerFilter, FREL, "Rel", 0);
mappingComps["freleaseKnob"] = freleaseKnob;
}
if (name == "lfoFrequencyKnob"){
lfoFrequencyKnob = addKnob (x, y, d, ownerFilter, LFOFREQ, "Freq", 0);
mappingComps["lfoFrequencyKnob"] = lfoFrequencyKnob;
}
if (name == "lfoAmt1Knob"){
lfoAmt1Knob = addKnob (x, y, d, ownerFilter, LFO1AMT, "Pitch", 0);
mappingComps["lfoAmt1Knob"] = lfoAmt1Knob;
}
if (name == "lfoAmt2Knob"){
lfoAmt2Knob = addKnob (x, y, d, ownerFilter, LFO2AMT, "PWM", 0);
mappingComps["lfoAmt2Knob"] = lfoAmt2Knob;
}
if (name == "lfoSinButton"){
lfoSinButton = addButton (x, y, w, h, ownerFilter, LFOSINWAVE, "Sin");
mappingComps["lfoSinButton"] = lfoSinButton;
}
if (name == "lfoSquareButton"){
lfoSquareButton = addButton (x, y, w, h, ownerFilter, LFOSQUAREWAVE, "SQ");
mappingComps["lfoSquareButton"] = lfoSquareButton;
}
if (name == "lfoSHButton"){
lfoSHButton = addButton (x, y, w, h, ownerFilter, LFOSHWAVE, "S&H");
mappingComps["lfoSHButton"] = lfoSHButton;
}
if (name == "lfoOsc1Button"){
lfoOsc1Button = addButton (x, y, w, h, ownerFilter, LFOOSC1, "Osc1");
mappingComps["lfoOsc1Button"] = lfoOsc1Button;
}
if (name == "lfoOsc2Button"){
lfoOsc2Button = addButton (x, y, w, h, ownerFilter, LFOOSC2, "Osc2");
mappingComps["lfoOsc2Button"] = lfoOsc2Button;
}
if (name == "lfoFilterButton"){
lfoFilterButton = addButton (x, y, w, h, ownerFilter, LFOFILTER, "Filt");
mappingComps["lfoFilterButton"] = lfoFilterButton;
}
if (name == "lfoPwm1Button"){
lfoPwm1Button = addButton (x, y, w, h, ownerFilter, LFOPW1, "Osc1");
mappingComps["lfoPwm1Button"] = lfoPwm1Button;
}
if (name == "lfoPwm2Button"){
lfoPwm2Button = addButton (x, y, w, h, ownerFilter, LFOPW2, "Osc2");
mappingComps["lfoPwm2Button"] = lfoPwm2Button;
}
if (name == "hardSyncButton"){
hardSyncButton = addButton (x, y, w, h, ownerFilter, OSC2HS, "Sync");
mappingComps["hardSyncButton"] = hardSyncButton;
}
if (name == "osc1SawButton"){
osc1SawButton = addButton (x, y, w, h, ownerFilter, OSC1Saw, "S");
mappingComps["osc1SawButton"] = osc1SawButton;
}
if (name == "osc2SawButton"){
osc2SawButton = addButton (x, y, w, h, ownerFilter, OSC2Saw, "S");
mappingComps["osc2SawButton"] = osc2SawButton;
}
if (name == "osc1PulButton"){
osc1PulButton = addButton (x, y, w, h, ownerFilter, OSC1Pul, "P");
mappingComps["osc1PulButton"] = osc1PulButton;
}
if (name == "osc2PulButton"){
osc2PulButton = addButton (x, y, w, h, ownerFilter, OSC2Pul, "P");
mappingComps["osc2PulButton"] = osc2PulButton;
}
if (name == "pitchQuantButton"){
pitchQuantButton = addButton (x, y, w, h, ownerFilter, OSCQuantize, "Step");
mappingComps["pitchQuantButton"] = pitchQuantButton;
}
if (name == "filterBPBlendButton"){
filterBPBlendButton = addButton (x, y, w, h, ownerFilter, BANDPASS, "Bp");
mappingComps["filterBPBlendButton"] = filterBPBlendButton;
}
if (name == "fourPoleButton"){
fourPoleButton = addButton (x, y, w, h, ownerFilter, FOURPOLE, "24");
mappingComps["fourPoleButton"] = fourPoleButton;
}
if (name == "filterHQButton"){
filterHQButton = addButton (x, y, w, h, ownerFilter, FILTER_WARM, "HQ");
mappingComps["filterHQButton"] = filterHQButton;
}
if (name == "filterKeyFollowButton"){
filterKeyFollowButton = addButton (x, y, w, h, ownerFilter, FLT_KF, "Key");
mappingComps["filterKeyFollowButton"] = filterKeyFollowButton;
}
if (name == "unisonButton"){
unisonButton = addButton (x, y, w, h, ownerFilter, UNISON, "Uni");
mappingComps["unisonButton"] = unisonButton;
}
if (name == "tuneKnob"){
tuneKnob = addKnob (x, y, d, ownerFilter, TUNE, "Tune", 0.5);
mappingComps["tuneKnob"] = tuneKnob;
}
if (name == "transposeKnob"){
transposeKnob = addKnob (x, y, d, ownerFilter, OCTAVE, "Transpose", 0.5);
mappingComps["transposeKnob"] = transposeKnob;
}
if (name == "voiceDetuneKnob"){
voiceDetuneKnob =addKnob (x, y, d, ownerFilter, UDET, "VoiceDet", 0);
mappingComps["voiceDetuneKnob"] = voiceDetuneKnob;
}
if (name == "bendLfoRateKnob"){
bendLfoRateKnob = addKnob (x, y, d, ownerFilter, BENDLFORATE, "ModRate", 0.4);
mappingComps["bendLfoRateKnob"] = bendLfoRateKnob;
}
if (name == "veloFltEnvKnob"){
veloFltEnvKnob = addKnob (x, y, d, ownerFilter, VFLTENV, "VFE", 0);
mappingComps["veloFltEnvKnob"] = veloFltEnvKnob;
}
if (name == "veloAmpEnvKnob"){
veloAmpEnvKnob = addKnob (x, y, d, ownerFilter, VAMPENV, "VAE", 0);
mappingComps["veloAmpEnvKnob"] = veloAmpEnvKnob;
}
if (name == "midiLearnButton"){
midiLearnButton = addButton (x, y, w, h, ownerFilter, MIDILEARN, "LEA");
mappingComps["midiLearnButton"] = midiLearnButton;
}
if (name == "midiUnlearnButton"){
midiUnlearnButton = addButton (x, y, w, h, ownerFilter, UNLEARN, "UNL");
mappingComps["midiUnlearnButton"] = midiUnlearnButton;
}
if (name == "pan1Knob"){
pan1Knob = addKnob (x, y, d, ownerFilter, PAN1, "1", 0.5);
mappingComps["pan1Knob"] = pan1Knob;
}
if (name == "pan2Knob"){
pan2Knob = addKnob (x, y, d, ownerFilter, PAN2, "2", 0.5);
mappingComps["pan2Knob"] = pan2Knob;
}
if (name == "pan3Knob"){
pan3Knob = addKnob (x, y, d, ownerFilter, PAN3, "3", 0.5);
mappingComps["pan3Knob"] = pan3Knob;
}
if (name == "pan4Knob"){
pan4Knob = addKnob (x, y, d, ownerFilter, PAN4, "4", 0.5);
mappingComps["pan4Knob"] = pan4Knob;
}
if (name == "pan5Knob"){
pan5Knob = addKnob (x, y, d, ownerFilter, PAN5, "5", 0.5);
mappingComps["pan5Knob"] = pan5Knob;
}
if (name == "pan6Knob"){
pan6Knob = addKnob (x, y, d, ownerFilter, PAN6, "6", 0.5);
mappingComps["pan6Knob"] = pan6Knob;
}
if (name == "pan7Knob"){
pan7Knob = addKnob (x, y, d, ownerFilter, PAN7, "7", 0.5);
mappingComps["pan7Knob"] = pan7Knob;
}
if (name == "pan8Knob"){
pan8Knob = addKnob (x, y, d, ownerFilter, PAN8, "8", 0.5);
mappingComps["pan8Knob"] = pan8Knob;
}
if (name == "bendOsc2OnlyButton"){
bendOsc2OnlyButton = addButton (x, y, w, h, ownerFilter, BENDOSC2, "Osc2");
mappingComps["bendOsc2OnlyButton"] = bendOsc2OnlyButton;
}
if (name == "bendRangeButton"){
bendRangeButton = addButton (x, y, w, h, ownerFilter, BENDRANGE, "12");
mappingComps["bendRangeButton"] = bendRangeButton;
}
if (name == "asPlayedAllocButton"){
asPlayedAllocButton = addButton (x, y, w, h, ownerFilter, ASPLAYEDALLOCATION, "APA");
mappingComps["asPlayedAllocButton"] = asPlayedAllocButton;
}
if (name == "filterDetuneKnob"){
filterDetuneKnob = addKnob (x, y, d, ownerFilter, FILTERDER, "Flt", 0.2);
mappingComps["filterDetuneKnob"] = filterDetuneKnob;
}
if (name == "portamentoDetuneKnob"){
portamentoDetuneKnob = addKnob (x, y, d, ownerFilter, PORTADER, "Port", 0.2);
mappingComps["portamentoDetuneKnob"] = portamentoDetuneKnob;
}
if (name == "envelopeDetuneKnob"){
envelopeDetuneKnob = addKnob (x, y, d, ownerFilter, ENVDER, "Env", 0.2);
mappingComps["envelopeDetuneKnob"] = envelopeDetuneKnob;
}
if (name == "voiceSwitch"){
voiceSwitch = addList (x, y, w, h, ownerFilter, VOICE_COUNT, "VoiceCount", "voices");
mappingComps["voiceSwitch"] = voiceSwitch;
}
if (name == "legatoSwitch"){
legatoSwitch = addList (x, y, w, h, ownerFilter, LEGATOMODE, "Legato", "legato");
mappingComps["legatoSwitch"] = legatoSwitch;
}
if (name == "menu")
{
ImageButton *img = addMenuButton (x, y, d, "menu");
mappingComps["menu"] = img;
}
/*
if (name == "guisize") {
xScreen = x;
yScreen = y;
if (processor.getShowPresetBar()) {
setSize(xScreen, yScreen + 40);
}
else {
setSize(xScreen, yScreen);
}
}
*/
//DBG(" Name: " << name << " X: " <<x <<" Y: "<<y);
}
}
}
presetBar.reset(new PresetBar(*this));
addAndMakeVisible(*presetBar);
presetBar->setVisible(processor.getShowPresetBar());
presetBar->leftClicked = [this](juce::Point<int> &pos){
PopupMenu menu;
for (int i = 0; i < processor.getNumPrograms(); ++i)
{
menu.addItem (i + progStart + 1,
processor.getProgramName (i),
true,
i == processor.getCurrentProgram());
}
int result = menu.showAt (Rectangle<int> (pos.getX(), pos.getY(), 1, 1));
if (result >= (progStart + 1) && result <= (progStart + processor.getNumPrograms())){
result -= 1;
result -= progStart;
processor.setCurrentProgram (result);
}
};
resized();
}
// Prepare data
if (voiceSwitch)
{
for (int i = 1; i <= 32; ++i)
{
voiceSwitch->addChoice (String (i));
}
auto voiceOption = ownerFilter.getPluginState().getParameter (ownerFilter.getEngineParameterId (VOICE_COUNT))->getValue();
voiceSwitch->setValue (voiceOption, dontSendNotification);
}
if (legatoSwitch)
{
legatoSwitch->addChoice ("Keep All");
legatoSwitch->addChoice ("Keep Filter Envelope");
legatoSwitch->addChoice ("Keep Amplitude Envelope");
legatoSwitch->addChoice ("Retrig");
auto legatoOption = ownerFilter.getPluginState().getParameter (ownerFilter.getEngineParameterId (LEGATOMODE))->getValue();
legatoSwitch->setValue (legatoOption, dontSendNotification);
}
createMenu();
ownerFilter.addChangeListener (this);
scaleFactorChanged();
repaint();
}
ObxdAudioProcessorEditor::~ObxdAudioProcessorEditor()
{
processor.removeChangeListener (this);
// deleteAllChildren(); // WATCH OUT!
}
void ObxdAudioProcessorEditor::scaleFactorChanged()
{
// update background
const bool highResolutionDisplay = isHighResolutionDisplay();
const float scaleFactor = getScaleFactor();
// notify child components
for (int i = 0; i < getNumChildComponents(); i++)
{
ScalableComponent* object =
dynamic_cast<ScalableComponent*>(getChildComponent(i));
if (object != nullptr)
{
object->setScaleFactor(scaleFactor, highResolutionDisplay);
}
}
// update look and feel
// redraw everything
backgroundImage = getScaledImageFromCache("main", scaleFactor, highResolutionDisplay);
int width = backgroundImage.getWidth();
int height = backgroundImage.getHeight();
if (!highResolutionDisplay)
{
if (scaleFactor == 1.5f)
{
width = roundFloatToInt(width * 0.75f);
height = roundFloatToInt(height * 0.75f);
}
else if (scaleFactor == 2.0f)
{
width /= 2;
height /= 2;
}
} else {
if (scaleFactor == 1.0f) //2x image
{
width /= 2;
height /= 2;
}
else if (scaleFactor == 1.5f) //4x images =>150%
{
width = roundFloatToInt(width * (0.25f + 0.125f));
height = roundFloatToInt(height * (0.25f + 0.125f));
}
else if (scaleFactor == 2.0f) //4x images =>200x
{
width /= 2;
height /= 2;
}
}
if (processor.getShowPresetBar())
{
setSize(width, height + presetBar->getHeight());
presetBar->setBounds((width - presetBar->getWidth()) / 2, height, presetBar->getWidth(), presetBar->getHeight());
} else
setSize(width, height);
}
void ObxdAudioProcessorEditor::placeLabel (int x, int y, String text)
{
Label* lab = new Label();
lab->setBounds (x, y, 110, 20);
lab->setJustificationType (Justification::centred);
lab->setText (text,dontSendNotification);
lab->setInterceptsMouseClicks (false, true);
addAndMakeVisible (lab);
}
ButtonList* ObxdAudioProcessorEditor::addList (int x, int y, int width, int height, ObxdAudioProcessor& filter, int parameter, String /*name*/, String imgName)
{
#if JUCE_WINDOWS || JUCE_LINUX
ButtonList *bl = new ButtonList (imgName, height, &processor);
#else
ButtonList *bl = new ButtonList (imgName, height, &processor);
#endif
buttonListAttachments.add (new ButtonList::ButtonListAttachment (filter.getPluginState(),
filter.getEngineParameterId (parameter),
*bl));
bl->setBounds (x, y, width, height);
addAndMakeVisible (bl);
return bl;
}
Knob* ObxdAudioProcessorEditor::addKnob (int x, int y, int d, ObxdAudioProcessor& filter, int parameter, String /*name*/, float defval)
{
Knob* knob = new Knob ("knob", 48, &processor);
knobAttachments.add (new Knob::KnobAttachment (filter.getPluginState(),
filter.getEngineParameterId (parameter),
*knob));
knob->setSliderStyle (Slider::RotaryVerticalDrag);
knob->setTextBoxStyle (knob->NoTextBox, true, 0, 0);
knob->setRange (0, 1);
knob->setBounds (x, y, d+(d/6), d+(d/6));
knob->setTextBoxIsEditable (false);
knob->setDoubleClickReturnValue (true, defval);
knob->setValue (filter.getPluginState().getParameter (filter.getEngineParameterId (parameter))->getValue());
addAndMakeVisible (knob);
return knob;
}
void ObxdAudioProcessorEditor::clean()
{
this->removeAllChildren();
}
TooglableButton* ObxdAudioProcessorEditor::addButton (int x, int y, int w, int h, ObxdAudioProcessor& filter, int parameter, String name)
{
TooglableButton* button = new TooglableButton ("button", &processor);
if (parameter != UNLEARN){
toggleAttachments.add (new AudioProcessorValueTreeState::ButtonAttachment (filter.getPluginState(),
filter.getEngineParameterId (parameter),
*button));
} else {
button->addListener(this);
}
button->setBounds (x, y, w, h);
button->setButtonText (name);
button->setToggleState(filter.getPluginState().getParameter (filter.getEngineParameterId (parameter))->getValue(),
dontSendNotification);
addAndMakeVisible (button);
return button;
}
Rectangle<int> ObxdAudioProcessorEditor::transformBounds(int x, int y, int w, int h)
{
if (getScaleFactor() == 1.0f)
return Rectangle<int>(x, y, w, h);
return Rectangle<int>(x, y, w, h).toFloat().transformedBy(AffineTransform::scale(getScaleFactor())).toNearestInt();
}
ImageButton* ObxdAudioProcessorEditor::addMenuButton (int x, int y, int d, String imgName)
{
ImageMenu* imageButton = new ImageMenu(imgName, &processor);
imageButtons.add (imageButton);
imageButton->setBounds (x, y, d, d);
imageButton->onClick = [this](){
ImageButton *imageButton = this->imageButtons[0];
auto x = imageButton->getScreenX();
auto y = imageButton->getScreenY();
auto dx = imageButton->getWidth();
auto pos = Point<int> (x, y + dx);
resultFromMenu (pos);
};
addAndMakeVisible (imageButton);
return imageButton;
}
void ObxdAudioProcessorEditor::rebuildComponents (ObxdAudioProcessor& ownerFilter)
{
skinFolder = ownerFilter.getCurrentSkinFolder();
ownerFilter.removeChangeListener (this);
// deleteAllChildren(); // WATCH OUT!
setSize (1440, 450);
ownerFilter.addChangeListener (this);
repaint();
}
void ObxdAudioProcessorEditor::createMenu ()
{
popupMenus.clear();
PopupMenu* menu = new PopupMenu();
PopupMenu progMenu;
PopupMenu bankMenu;
PopupMenu skinMenu;
PopupMenu fileMenu;
//PopupMenu viewMenu;
PopupMenu midiMenu;
skins = processor.getSkinFiles();
banks = processor.getBankFiles();
{
fileMenu.addItem(static_cast<int>(MenuAction::ImportPreset),
"Import Preset...",
true,
false);
fileMenu.addItem(static_cast<int>(MenuAction::ImportBank),
"Import Bank...",
true,
false);
fileMenu.addSeparator();
fileMenu.addItem(static_cast<int>(MenuAction::ExportPreset),
"Export Preset...",
true,
false);
fileMenu.addItem(static_cast<int>(MenuAction::ExportBank),
"Export Bank...",
true,
false);
fileMenu.addSeparator();
fileMenu.addItem(static_cast<int>(MenuAction::NewPreset),
"New Preset...",
true,//enableNewPresetOption,
false);
fileMenu.addItem(static_cast<int>(MenuAction::RenamePreset),
"Rename Preset...",
true,
false);
fileMenu.addItem(static_cast<int>(MenuAction::SavePreset),
"Save Preset...",
true,
false);
fileMenu.addItem(static_cast<int>(MenuAction::DeletePreset),
"Delete Preset...",
true,
false);
/*
fileMenu.addItem(static_cast<int>(MenuAction::DeleteBank),
"Delete Bank...",
true,
false);
*/
menu->addSubMenu("File", fileMenu);
}
{
for (int i = 0; i < processor.getNumPrograms(); ++i)
{
progMenu.addItem (i + progStart + 1,
processor.getProgramName (i),
true,
i == processor.getCurrentProgram());
}
menu->addSubMenu("Programs", progMenu);
}
menu->addItem(progStart + 1000, "Preset Bar", true, processor.showPresetBar);
{
const String currentBank = processor.getCurrentBankFile().getFileName();
for (int i = 0; i < banks.size(); ++i)
{
const File bank = banks.getUnchecked (i);
bankMenu.addItem (i + bankStart + 1,
bank.getFileNameWithoutExtension(),
true,
bank.getFileName() == currentBank);
}
menu->addSubMenu ("Banks", bankMenu);
}
{
for (int i = 0; i < skins.size(); ++i)
{
const File skin = skins.getUnchecked (i);
skinMenu.addItem (i + skinStart + 1,
skin.getFileName(),
true,
skin.getFileName() == skinFolder.getFileName());
}
menu->addSubMenu ("Themes", skinMenu);
// About // menu.addItem(1, String("Release ") + String(JucePlugin_VersionString).dropLastCharacters(2), false);
}
//menu->addSubMenu ("View", viewMenu);
menuMidiNum = progStart +2000;
createMidi(menuMidiNum, midiMenu);
menu->addSubMenu ("MIDI", midiMenu);
popupMenus.add (menu);
PopupMenu scaleMenu;
menuScaleNum =progStart +2000 + 3000;
scaleMenu.addItem(menuScaleNum, "1x", true, getScaleFactor() == 1.0f);
scaleMenu.addItem(menuScaleNum+1, "1.5x", true, getScaleFactor() == 1.5f);
scaleMenu.addItem(menuScaleNum+2, "2x", true, getScaleFactor() == 2.0f);
menu->addSubMenu("GUI Size", scaleMenu, true);
PopupMenu helpMenu;
String version = String("Release ") + String(JucePlugin_VersionString).dropLastCharacters(2);
helpMenu.addItem(menuScaleNum+3, version, false);
#ifndef WIN32
helpMenu.addItem(menuScaleNum+4, "Manual", true);
#endif
menu->addSubMenu("Help", helpMenu, true);
}
void ObxdAudioProcessorEditor::createMidi(int menuNo, PopupMenu &menuMidi) {
File midi_dir = processor.getMidiFolder();
File default_file = midi_dir.getChildFile("Default.xml");
if(default_file.exists()){
if (processor.currentMidiPath != default_file.getFullPathName()){
menuMidi.addItem(menuNo++, default_file.getFileNameWithoutExtension(), true, false);
} else {
menuMidi.addItem(menuNo++, default_file.getFileNameWithoutExtension(), true, true);
}
midiFiles.add(default_file.getFullPathName());
}
File custom_file = midi_dir.getChildFile("Custom.xml");
if(custom_file.exists()){
if (processor.currentMidiPath != custom_file.getFullPathName()){
menuMidi.addItem(menuNo++, custom_file.getFileNameWithoutExtension(), true, false);
} else {
menuMidi.addItem(menuNo++, custom_file.getFileNameWithoutExtension(), true, true);
}
midiFiles.add(custom_file.getFullPathName());
}
DirectoryIterator iter (midi_dir, true, "*.xml");
StringArray list;
while (iter.next())
{
list.add(iter.getFile().getFullPathName());
}
list.sort(true);
for (int i =0; i < list.size() ; i ++){
File f (list[i]);
if (f.getFileNameWithoutExtension() != "Default" && f.getFileNameWithoutExtension() != "Custom" && f.getFileNameWithoutExtension() != "Config") {
if (processor.currentMidiPath != f.getFullPathName()){
menuMidi.addItem(menuNo++, f.getFileNameWithoutExtension(), true, false);
} else {
menuMidi.addItem(menuNo++, f.getFileNameWithoutExtension(), true, true);
}
midiFiles.add(f.getFullPathName());
}
}
}
void ObxdAudioProcessorEditor::resultFromMenu (const Point<int> pos)
{
createMenu();
int result = popupMenus[0]->showAt (Rectangle<int> (pos.getX(), pos.getY(), 1, 1));
if (result >= (skinStart + 1) && result <= (skinStart + skins.size()))
{
result -= 1;
result -= skinStart;
const File newSkinFolder = skins.getUnchecked (result);
processor.setCurrentSkinFolder (newSkinFolder.getFileName());
//rebuildComponents (processor);
clean();
loadSkin (processor);
}
else if (result >= (bankStart + 1) && result <= (bankStart + banks.size()))
{
result -= 1;
result -= bankStart;
const File bankFile = banks.getUnchecked (result);
processor.loadFromFXBFile (bankFile);
//clean();
//loadSkin (processor); // Check this
}
else if (result >= (progStart + 1) && result <= (progStart + processor.getNumPrograms()))
{
result -= 1;
result -= progStart;
processor.setCurrentProgram (result);
//clean();
//loadSkin (processor); // Check this
}
else if (result < progStart){
MenuActionCallback(result);
}
else if (result == progStart + 1000){
processor.setShowPresetBar(!processor.getShowPresetBar());
//createMenu();
updatePresetBar(true);
}
else if (result >= menuScaleNum){
if (result ==menuScaleNum){
ScalableComponent::setScaleFactor(1.0f, isHighResolutionDisplay());
processor.setGuiSize(1);
}
else if (result == menuScaleNum+1){
ScalableComponent::setScaleFactor(1.5f, isHighResolutionDisplay());
processor.setGuiSize(2);
}
else if (result == menuScaleNum+2) {
ScalableComponent::setScaleFactor(2.0f, isHighResolutionDisplay());
processor.setGuiSize(4);
}
else if (result == menuScaleNum+4) {
File manualFile = processor.getDocumentFolder().getChildFile("OB-Xd Manual.pdf");
openInPdf(manualFile);
}
}
else if (result >= menuMidiNum){
unsigned int selected_idx = result - menuMidiNum;
if (selected_idx >= 0 && selected_idx < midiFiles.size()){
File f(midiFiles[selected_idx]);
if (f.exists()) {
processor.currentMidiPath = midiFiles[selected_idx];
processor.bindings.loadFile(f);
processor.updateConfig();
//createMenu();
}
}
}
}
void ObxdAudioProcessorEditor::updatePresetBar(bool resize){
DBG(" H: " << getHeight() <<" W:" <<getWidth() << " CW:"<<presetBar->getWidth() << " CH" <<presetBar->getHeight() << " CX:" <<presetBar->getX() << " CY: " <<presetBar->getY());
if (processor.getShowPresetBar()) {
if (resize) {
this->setSize(this->getWidth(), this->getHeight() + presetBar->getHeight());
}
presetBar->setVisible(true);
presetBar->update();
presetBar->setBounds((getWidth() - presetBar->getWidth()) / 2, getHeight() -presetBar->getHeight(), presetBar->getWidth(), presetBar->getHeight());
}
else if (presetBar->isVisible()) {
if (resize) {
this->setSize(this->getWidth(), this->getHeight() - presetBar->getHeight());
}
presetBar->setVisible(false);
}
}
void ObxdAudioProcessorEditor::MenuActionCallback(int action){
if (action == MenuAction::ImportBank)
{
fileChooser = std::make_unique<juce::FileChooser>("Import Bank (*.fxb)", juce::File(), "*.fxb", true);
if (fileChooser->browseForFileToOpen()) {
File result = fileChooser->getResult();
auto name = result.getFileName().replace("%20", " ");
auto file = processor.getBanksFolder().getChildFile(name);
if (result == file || result.copyFileTo(file)){
processor.loadFromFXBFile(file);
processor.scanAndUpdateBanks();
//createMenu();
}
}
};
if (action == MenuAction::ExportBank)
{
auto file = processor.getDocumentFolder().getChildFile("Banks");
FileChooser myChooser ("Export Bank (*.fxb)", file, "*.fxb", true);
if(myChooser.browseForFileToSave(true))
{
File result = myChooser.getResult();
String temp = result.getFullPathName();
if (!temp.endsWith(".fxb")) {
temp += ".fxb";
}
processor.saveBank(File(temp));
}
};
if (action == MenuAction::DeleteBank)
{
if(NativeMessageBox::showOkCancelBox(AlertWindow::NoIcon, "Delete Bank", "Delete current bank: " + processor.currentBank + "?")){
processor.deleteBank();
}
}
if (action == MenuAction::SavePreset)
{
auto presetName = processor.currentPreset;
if (presetName.isEmpty() )
{
processor.saveBank();
return;
}
processor.savePreset();
processor.saveBank();
}
if (action == MenuAction::NewPreset)
{
setPresetNameWindow = std::make_unique<SetPresetNameWindow>();
//preventBackgroundClick();
addAndMakeVisible(setPresetNameWindow.get());
resized();
auto callback = [this](int i, juce::String name)
{
if (i)
{
if (name.isNotEmpty())
{
processor.newPreset(name);
//createMenu();
}
}
setPresetNameWindow.reset();
//preventBackgroundClickComponent.reset();
};
setPresetNameWindow->callback = callback;
setPresetNameWindow->grabTextEditorFocus();
return;
}
if (action == MenuAction::RenamePreset)
{
setPresetNameWindow = std::make_unique<SetPresetNameWindow>();
//preventBackgroundClick();
setPresetNameWindow->setText(processor.getProgramName(processor.getCurrentProgram()));
addAndMakeVisible(setPresetNameWindow.get());
resized();
auto callback = [this](int i, juce::String name)
{
if (i)
{
if (name.isNotEmpty())
{
processor.changePresetName(name);
//createMenu();
}
}
setPresetNameWindow.reset();
//preventBackgroundClickComponent.reset();
};
setPresetNameWindow->callback = callback;
setPresetNameWindow->grabTextEditorFocus();
return;
}
if (action == MenuAction::DeletePreset)
{
if(NativeMessageBox::showOkCancelBox(AlertWindow::NoIcon, "Delete Preset", "Delete current preset " + processor.currentPreset + "?")){
processor.deletePreset();
//createMenu();
}
return;
}
if (action == MenuAction::ImportPreset)
{
DBG("Import Preset");
fileChooser = std::make_unique<juce::FileChooser>("Import Preset (*.fxp)", juce::File(), "*.fxp", true);
if (fileChooser->browseForFileToOpen()) {
File result = fileChooser->getResult();
//auto name = result.getFileName().replace("%20", " ");
//auto file = processor.getPresetsFolder().getChildFile(name);
DBG("Import Preset: " << result.getFileName());
//if (result == file || result.copyFileTo(file)){
processor.loadPreset(result);
//createMenu();
//}
}
};
if (action == MenuAction::ExportPreset)
{
auto file = processor.getPresetsFolder();
FileChooser myChooser ("Export Preset (*.fxp)", file, "*.fxp", true);
if(myChooser.browseForFileToSave(true))
{
File result = myChooser.getResult();
String temp = result.getFullPathName();
if (!temp.endsWith(".fxp")) {
temp += ".fxp";
}
processor.savePreset(File(temp));
}
};
}
void ObxdAudioProcessorEditor::deleteBank()
{
}
void ObxdAudioProcessorEditor::nextProgram() {
int cur = processor.getCurrentProgram() + 1;
if (cur == processor.getNumPrograms()) {
cur = 0;
}
processor.setCurrentProgram (cur, false);
needNotifytoHost = true;
countTimer = 0;
// Define for win and mac?
//clean();
//loadSkin (processor); // check
}
void ObxdAudioProcessorEditor::prevProgram() {
int cur = processor.getCurrentProgram() - 1;
if (cur < 0) {
cur = processor.getNumPrograms() - 1;
}
processor.setCurrentProgram (cur, false);
needNotifytoHost = true;
countTimer = 0;
//clean();
//loadSkin (processor);
}
void ObxdAudioProcessorEditor::buttonClicked (Button* b)
{
/*
auto imageButton = dynamic_cast<ImageButton*> (b);
if (imageButton == imageButtons[0])
{
auto x = imageButton->getScreenX();
auto y = imageButton->getScreenY();
auto dx = imageButton->getWidth();
auto pos = Point<int> (x, y + dx);
resultFromMenu (pos);
}*/
auto toggleButton = dynamic_cast<TooglableButton*> (b);
if (toggleButton == midiUnlearnButton){
if (midiUnlearnButton->getToggleState()){
countTimerForLed = 0;
processor.getMidiMap().reset();
processor.getMidiMap().set_default();
processor.sendChangeMessage();
}
}
}
//==============================================================================
void ObxdAudioProcessorEditor::updateFromHost() {
for (int i = 0; i < knobAttachments.size(); ++i)
{
knobAttachments[i]->updateToSlider();
}
/*
for (int i = 0; i < toggleAttachments.size(); ++i)
{
toggleAttachments[i]->updateToSlider();
}*/
for (int i = 0; i < buttonListAttachments.size(); ++i)
{
buttonListAttachments[i]->updateToSlider();
}
// Set to unlearn to false
//if ( midiUnlearnButton && midiUnlearnButton->getToggleState()) {
// Thread::sleep(500);
// midiUnlearnButton->setToggleState(false, NotificationType:: sendNotification);
//}
repaint();
}
void ObxdAudioProcessorEditor::changeListenerCallback (ChangeBroadcaster* source)
{
updateFromHost();
}
void ObxdAudioProcessorEditor::mouseUp (const MouseEvent& e)
{
if (e.mods.isRightButtonDown() || e.mods.isCommandDown())
{
resultFromMenu (e.getMouseDownScreenPosition());
}
}
void ObxdAudioProcessorEditor::handleAsyncUpdate() {
scaleFactorChanged();
repaint();
}
void ObxdAudioProcessorEditor::paint(Graphics& g)
{
const float newPhysicalPixelScaleFactor =
g.getInternalContext().getPhysicalPixelScaleFactor();
if (newPhysicalPixelScaleFactor != processor.physicalPixelScaleFactor)
{
processor.physicalPixelScaleFactor = newPhysicalPixelScaleFactor;
//triggerAsyncUpdate();
}
g.fillAll (Colours::black);
// background gui
if(processor.showPresetBar){
g.drawImage(backgroundImage,
0, 0, getWidth(), getHeight() - 40,
0, 0, backgroundImage.getWidth(), backgroundImage.getHeight());
} else {
g.drawImage(backgroundImage,
0, 0, getWidth(), getHeight(),
0, 0, backgroundImage.getWidth(), backgroundImage.getHeight());
}
/*
#if JUCE_WINDOWS || JUCE_LINUX
const File mainFile(skinFolder.getChildFile("main.png"));
#else
const File mainFile(skinFolder.getChildFile("main@2x.png"));
#endif
if (!notLoadSkin && skinFolder.exists() && mainFile.exists())
{
const Image image = ImageCache::getFromFile(mainFile);
#if JUCE_WINDOWS || JUCE_LINUX
g.drawImage (image,
0, 0, image.getWidth(), image.getHeight(),
0, 0, image.getWidth(), image.getHeight());
#else
g.drawImage (image,
0, 0, image.getWidth()/2, image.getHeight()/2,
0, 0, image.getWidth(), image.getHeight());
#endif
}
else
{
const Image image = ImageCache::getFromMemory(BinaryData::main_png, BinaryData::main_pngSize);
// g.setImageResamplingQuality(Graphics::ResamplingQuality::highResamplingQuality);
g.drawImage (image,
0, 0, image.getWidth(), image.getHeight(),
0, 0, image.getWidth(), image.getHeight());
}
*/
}
bool ObxdAudioProcessorEditor::isInterestedInFileDrag(const StringArray& files)
{
StringArray extensions;
extensions.add(".fxp");
extensions.add(".fxb");
if (files.size() == 1) {
File file = File(files[0]);
String ext = file.getFileExtension().toLowerCase();
return file.existsAsFile() && extensions.contains(ext);
} else {
for (int q = 0; q < files.size(); q++) {
File file = File(files[q]);
String ext = file.getFileExtension().toLowerCase();
if (ext == ".fxb" || ext == ".fxp") {
return true;
}
}
}
return false;
}
void ObxdAudioProcessorEditor::filesDropped(const StringArray& files, int x, int y)
{
if (files.size() == 1) {
File file = File(files[0]);
String ext = file.getFileExtension().toLowerCase();
if (ext == ".fxp") {
processor.loadPreset(file);
//createMenu();
} else if (ext == ".fxb") {
auto name = file.getFileName().replace("%20", " ");
auto result = processor.getBanksFolder().getChildFile(name);
if (file.copyFileTo(result)){
processor.loadFromFXBFile(result);
processor.scanAndUpdateBanks();
//createMenu();
}
}
} else {
int i = processor.getCurrentProgram();
for (int q = 0; q < files.size(); q++) {
File file = File(files[q]);
String ext = file.getFileExtension().toLowerCase();
if (ext == ".fxp") {
processor.setCurrentProgram(i++);
processor.loadPreset(file);
}
if (i >=processor.getNumPrograms()){
i = 0;
}
}
processor.sendChangeMessage();
//createMenu();
}
}
/*
bool ObxdAudioProcessorEditor::keyPressed(const KeyPress & press) {
if (press.getKeyCode() == '+' || press.getKeyCode() == KeyPress::numberPadAdd)
{
nextProgram();
return false; // r+eturn true when the keypress was handled
}
if (press.getKeyCode() == '-' || press.getKeyCode() == KeyPress::numberPadSubtract)
{
prevProgram();
return false; // return true when the keypress was handled
}
return false; // return false if you don't handle the keypress
}*/