commit e4730b8a4db0f0e4e7d48e6cd478f19764481ca4 parent 9c19f216c269fa3d407040c546f4ebaa232bca63 Author: trancy2k5 <63122430+trancy2k5@users.noreply.github.com> Date: Fri, 21 Jan 2022 22:11:53 +0100 - Created new bitmaps for the section: Arp/General and Patch Library. - Removed button "V" for quick selection. Now only load via Patch Library - New postCommandMessage (InitPatches, NextPatch, PrevPatch, SelectFirstPatch) added. - Asynchronous loading of first patch when "DUMP_SINGLE" is loaded - Fixed: Part Volume not bipolar - Added the following sections to the ARP/General section: (Patch Settings, Arpeggiator, Input, Softknobs) - Patch Library improved, you can load between ROM and File. - The last ROM bank or Mid/syx file is remembered and loaded as default when reloading. Diffstat:
14 files changed, 346 insertions(+), 225 deletions(-)
diff --git a/source/jucePlugin/VirusController.cpp b/source/jucePlugin/VirusController.cpp @@ -32,7 +32,7 @@ namespace Virus sendSysEx(constructMessage({MessageType::REQUEST_ARRANGEMENT})); for(uint8_t i=3; i<=8; ++i) - sendSysEx(constructMessage({MessageType::REQUEST_BANK_SINGLE, i})); + sendSysEx(constructMessage({MessageType::REQUEST_BANK_SINGLE, i})); startTimer(5); } @@ -1835,7 +1835,7 @@ namespace Virus {Parameter::Page::C, Parameter::Class::MULTI_PARAM, 36, "Part High Key", {0,127}, {},{}, false, true, false}, {Parameter::Page::C, Parameter::Class::MULTI_PARAM, 37, "Part Transpose", {0,127}, paramTo7bitSigned, textTo7bitSigned, false, false, false, true}, {Parameter::Page::C, Parameter::Class::MULTI_PARAM, 38, "Part Detune", {0,127}, paramTo7bitSigned, textTo7bitSigned, false, false, false, true}, - {Parameter::Page::C, Parameter::Class::MULTI_PARAM, 39, "Part Volume", {0,127}, paramTo7bitSigned,textTo7bitSigned, true, false, false, true}, + {Parameter::Page::C, Parameter::Class::MULTI_PARAM, 39, "Part Volume", {0,127}, paramTo7bitSigned,textTo7bitSigned, true, false, false, false}, {Parameter::Page::C, Parameter::Class::MULTI_PARAM, 40, "Part Midi Volume Init", {0,127}, {},{}, false, true, false}, {Parameter::Page::C, Parameter::Class::MULTI_PARAM, 41, "Part Output Select", {0,14}, numToOutputSelect,{}, false, true, false}, {Parameter::Page::C, Parameter::Class::GLOBAL, 45, "Second Output Select", {0,15}, {},{}, false, true, false}, @@ -2035,7 +2035,19 @@ namespace Virus parseControllerDump(msg); } else - parseMessage(msg.sysex); + { + if (msg.sysex[6] == MessageType::DUMP_SINGLE) + { + //only call up when we have received the dump first + if (onMsgDone) { + onMsgDone(); + } + } + parseMessage(msg.sysex); + + + + } } m_virusOut.clear(); } diff --git a/source/jucePlugin/VirusController.h b/source/jucePlugin/VirusController.h @@ -429,6 +429,8 @@ namespace Virus void onStateLoaded(); juce::PropertiesFile* getConfig() { return m_config; } std::function<void()> onProgramChange = {}; + std::function<void()> onMsgDone = {}; + private: void timerCallback() override; static constexpr size_t kDataSizeInBytes = 256; // same for multi and single diff --git a/source/jucePlugin/assets2/main_background.png b/source/jucePlugin/assets2/main_background.png Binary files differ. diff --git a/source/jucePlugin/assets2/panel_3_marker_points.png b/source/jucePlugin/assets2/panel_3_marker_points.png Binary files differ. diff --git a/source/jucePlugin/assets2/panel_4_marker_points.png b/source/jucePlugin/assets2/panel_4_marker_points.png Binary files differ. diff --git a/source/jucePlugin/assets2/panels/panel_3.png b/source/jucePlugin/assets2/panels/panel_3.png Binary files differ. diff --git a/source/jucePlugin/assets2/panels/panel_4.png b/source/jucePlugin/assets2/panels/panel_4.png Binary files differ. diff --git a/source/jucePlugin/ui2/VirusEditor.cpp b/source/jucePlugin/ui2/VirusEditor.cpp @@ -93,13 +93,6 @@ VirusEditor::VirusEditor(VirusParameterBinding &_parameterBinding, AudioPluginAu m_patchName.setJustificationType(Justification::left); m_patchName.setFont(juce::Font("Register", "Normal", 30.f)); m_patchName.setEditable(false, true, true); - m_patchName.onTextChange = [this]() { - auto text = m_patchName.getText(); - if(text.trim().length() > 0) { - m_controller.setSinglePresetName(m_controller.getCurrentPart(), text); - m_arpEditor->refreshParts(); - } - }; addAndMakeVisible(m_patchName); //MainDisplay @@ -116,6 +109,7 @@ VirusEditor::VirusEditor(VirusParameterBinding &_parameterBinding, AudioPluginAu m_ToolTip.setJustificationType(Justification::centred); m_ToolTip.setAlpha(0.90); addAndMakeVisible(m_ToolTip); + m_ToolTip.setVisible(false); //MainDisplay Value m_controlLabelValue.setBounds(1900, 35, 197, 58); @@ -131,21 +125,16 @@ VirusEditor::VirusEditor(VirusParameterBinding &_parameterBinding, AudioPluginAu m_PresetRight.setBounds(2199 - m_PresetRight.kWidth / 2, 62 - m_PresetRight.kHeight / 2, m_PresetRight.kWidth, m_PresetRight.kHeight); m_PresetLeft.onClick = [this]() { - processorRef.getController().setCurrentPartPreset(m_controller.getCurrentPart(), processorRef.getController().getCurrentPartBank(m_controller.getCurrentPart()), - std::max(0, processorRef.getController().getCurrentPartProgram(m_controller.getCurrentPart()) - 1)); + + postCommandMessage(VirusEditor::Commands::PrevPatch); postCommandMessage(VirusEditor::Commands::UpdateParts); }; m_PresetRight.onClick = [this]() { - processorRef.getController().setCurrentPartPreset(m_controller.getCurrentPart(), processorRef.getController().getCurrentPartBank(m_controller.getCurrentPart()), - std::min(127, processorRef.getController().getCurrentPartProgram(m_controller.getCurrentPart()) + 1)); + postCommandMessage(VirusEditor::Commands::NextPatch); postCommandMessage(VirusEditor::Commands::UpdateParts); }; - addAndMakeVisible(m_PresetPatchList); - m_PresetPatchList.setBounds(2133 - m_PresetPatchList.kWidth / 2, 62 - m_PresetPatchList.kHeight / 2, m_PresetPatchList.kWidth, m_PresetPatchList.kHeight); - m_PresetPatchList.onClick = [this]() {ShowMenuePatchList(); }; - //Show Version m_version.setText(std::string(g_pluginVersionString), NotificationType::dontSendNotification); m_version.setBounds(250, 1123, 50, 17); @@ -178,12 +167,17 @@ VirusEditor::VirusEditor(VirusParameterBinding &_parameterBinding, AudioPluginAu updateParts(); m_arpEditor->refreshParts(); }; - + m_controller.onMsgDone = [this]() + { + m_controller.onMsgDone = nullptr; + postCommandMessage(VirusEditor::Commands::InitPatches); + postCommandMessage(VirusEditor::Commands::SelectFirstPatch); + postCommandMessage(VirusEditor::Commands::UpdateParts); + }; + m_controller.getBankCount(); addMouseListener(this, true); setSize (kPanelWidth, kPanelHeight); - recreateControls(); - updateParts(); } VirusEditor::~VirusEditor() @@ -205,23 +199,26 @@ void VirusEditor::updateParts() bool singlePartOrInMulti = pt == 0 || multiMode; if (pt == m_controller.getCurrentPart()) { - int iZeroCount; - if (m_controller.getCurrentPartProgram(m_controller.getCurrentPart()) < 10) iZeroCount = 2; - else if (m_controller.getCurrentPartProgram(m_controller.getCurrentPart()) < 100) iZeroCount = 1; - else iZeroCount = 0; + int CurrentPart = m_controller.getCurrentPartProgram(m_controller.getCurrentPart()); const auto patchName = m_controller.getCurrentPartPresetName(pt); if(m_patchName.getText() != patchName) { - String sZero = ""; - for (int i=0; i<iZeroCount; i++) - { - sZero=sZero+"0"; + String sZero; + if (m_patchBrowser->GetIsFileMode()) + { + m_patchName.setText("["+juce::String(m_controller.getCurrentPart()+1) + +"][FILE] " + + sZero.paddedLeft('0',(CurrentPart<10)?2:(CurrentPart<100)?1:0) + + juce::String(m_patchBrowser->m_patchList.getSelectedRow(0))+": " + patchName, dontSendNotification); + } + else + { + m_patchName.setText("["+juce::String(m_controller.getCurrentPart()+1) + +"][" + getCurrentPartBankStr(m_controller.getCurrentPartBank(m_controller.getCurrentPart())) + "] " + + sZero.paddedLeft('0',(CurrentPart<10)?2:(CurrentPart<100)?1:0) + + juce::String(processorRef.getController().getCurrentPartProgram(m_controller.getCurrentPart())+1)+": " + patchName, dontSendNotification); } - m_patchName.setText("["+juce::String(m_controller.getCurrentPart()+1) - +"][" + getCurrentPartBankStr(m_controller.getCurrentPartBank(m_controller.getCurrentPart())) + "] " - + sZero - + juce::String(processorRef.getController().getCurrentPartProgram(m_controller.getCurrentPart())+1)+": " + patchName, NotificationType::dontSendNotification); } } } @@ -261,33 +258,6 @@ void VirusEditor::ShowMainMenue() addAndMakeVisible(m_mainMenu); } -void VirusEditor::ShowMenuePatchList() -{ - auto pt = m_controller.getCurrentPart(); - - selector.setLookAndFeel (&m_landfButtons); - selector.clear(); - - for (uint8_t b = 0; b < m_controller.getBankCount(); ++b) - { - const auto bank = virusLib::fromArrayIndex(b); - auto presetNames = m_controller.getSinglePresetNames(bank); - juce::PopupMenu p; - for (uint8_t j = 0; j < 128; j++) - { - const auto presetName = presetNames[j]; - p.addItem(presetNames[j], [this, bank, j, pt, presetName] { - m_controller.setCurrentPartPreset(pt, bank, j); - postCommandMessage(VirusEditor::Commands::UpdateParts); - //m_presetNames[pt].setButtonText(presetName); - }); - } - std::stringstream bankName; - bankName << "Bank " << static_cast<char>('A' + b); - selector.addSubMenu(std::string(bankName.str()), p); - } - selector.showMenu(juce::PopupMenu::Options()); -} void VirusEditor::applyToSections(std::function<void(Component *)> action) { @@ -349,14 +319,16 @@ void VirusEditor::mouseDrag(const juce::MouseEvent & event) updateControlLabel(event.eventComponent); } -void VirusEditor::mouseEnter(const juce::MouseEvent& event) { +void VirusEditor::mouseEnter(const juce::MouseEvent& event) +{ if (event.mouseWasDraggedSinceMouseDown()) { return; } updateControlLabel(event.eventComponent); } -void VirusEditor::mouseExit(const juce::MouseEvent& event) { +void VirusEditor::mouseExit(const juce::MouseEvent& event) +{ if (event.mouseWasDraggedSinceMouseDown()) { return; } @@ -367,8 +339,8 @@ void VirusEditor::mouseExit(const juce::MouseEvent& event) { m_ToolTip.setVisible(false); } -void VirusEditor::mouseDown(const juce::MouseEvent &event) { - +void VirusEditor::mouseDown(const juce::MouseEvent &event) +{ } void VirusEditor::mouseUp(const juce::MouseEvent & event) @@ -379,7 +351,8 @@ void VirusEditor::mouseUp(const juce::MouseEvent & event) m_patchName.setVisible(true); m_ToolTip.setVisible(false); } -void VirusEditor::mouseWheelMove(const juce::MouseEvent& event, const juce::MouseWheelDetails& wheel) { +void VirusEditor::mouseWheelMove(const juce::MouseEvent& event, const juce::MouseWheelDetails& wheel) +{ updateControlLabel(event.eventComponent); } @@ -399,7 +372,19 @@ void VirusEditor::handleCommandMessage(int commandId) { switch (commandId) { case Commands::Rebind: recreateControls(); - case Commands::UpdateParts: { updateParts(); m_arpEditor->refreshParts();}; + case Commands::UpdateParts: { updateParts(); m_arpEditor->refreshParts();}; break; + case Commands::InitPatches: { + m_patchBrowser->IntiPatches();}; break; + case Commands::PrevPatch: { + m_patchBrowser->m_patchList.selectRow(m_patchBrowser->m_patchList.getSelectedRow(0)-1,false,false); + };break; + case Commands::NextPatch: { + m_patchBrowser->m_patchList.selectRow(m_patchBrowser->m_patchList.getSelectedRow(0)+1,false,false); + };break; + case Commands::SelectFirstPatch: { + m_patchBrowser->m_patchList.selectRow(0,false,false); + };break; + default: return; } } @@ -410,7 +395,7 @@ void VirusEditor::recreateControls() removeChildComponent(m_lfoEditor.get()); removeChildComponent(m_fxEditor.get()); removeChildComponent(m_arpEditor.get()); - //removeChildComponent(m_patchBrowser.get()); + // removeChildComponent(m_patchBrowser.get()); m_oscEditor = std::make_unique<OscEditor>(m_parameterBinding); addChildComponent(m_oscEditor.get()); @@ -424,8 +409,8 @@ void VirusEditor::recreateControls() m_arpEditor = std::make_unique<ArpEditor>(m_parameterBinding, processorRef); addChildComponent(m_arpEditor.get()); - /*m_patchBrowser = std::make_unique<PatchBrowser>(m_parameterBinding, processorRef); - addChildComponent(m_patchBrowser.get());*/ + //m_patchBrowser = std::make_unique<PatchBrowser>(m_parameterBinding, processorRef); + //addChildComponent(m_patchBrowser.get()); m_mainButtons.updateSection(); resized(); diff --git a/source/jucePlugin/ui2/VirusEditor.h b/source/jucePlugin/ui2/VirusEditor.h @@ -31,6 +31,10 @@ public: None, Rebind = 0x100, UpdateParts = 0x101, + InitPatches = 0x102, + NextPatch = 0x103, + PrevPatch = 0x104, + SelectFirstPatch = 0x105 }; const int iSkinSizeWidth = 2501, iSkinSizeHeight = 1152; @@ -70,7 +74,7 @@ private: Buttons::PresetButtonLeft m_PresetLeft; Buttons::PresetButtonRight m_PresetRight; - Buttons::PresetButtonDown m_PresetPatchList; + //Buttons::PresetButtonDown m_PresetPatchList; struct PartButtons : juce::Component { PartButtons(); diff --git a/source/jucePlugin/ui2/Virus_Panel3_FxEditor.cpp b/source/jucePlugin/ui2/Virus_Panel3_FxEditor.cpp @@ -170,7 +170,7 @@ FxEditor::FxEditor(VirusParameterBinding &_parameterBinding, AudioPluginAudioPro m_reverbFeedback.setBounds(1052 - knobSize / 2, 854 - knobSize / 2, knobSize, knobSize); addAndMakeVisible(m_reverbType); - m_reverbType.setBounds(467+comboBoxXMargin - comboBox3Width / 2, 900 - comboBox3Height / 2, comboBox3Width, comboBox3Height); + m_reverbType.setBounds(467+comboBoxXMargin - comboBox3Width / 2, 854 - comboBox3Height / 2, comboBox3Width, comboBox3Height); _parameterBinding.bind(m_reverbDecayTime, Virus::Param_DelayRateReverbDecayTime); _parameterBinding.bind(m_reverbDaming, Virus::Param_DelayLfoShape); diff --git a/source/jucePlugin/ui2/Virus_Panel4_ArpEditor.cpp b/source/jucePlugin/ui2/Virus_Panel4_ArpEditor.cpp @@ -15,71 +15,105 @@ ArpEditor::ArpEditor(VirusParameterBinding &_parameterBinding, AudioPluginAudioP setupBackground(*this, m_background, BinaryData::panel_4_png, BinaryData::panel_4_pngSize); setBounds(m_background->getDrawableBounds().toNearestIntEdges()); - //MIDI settings - juce::String midiIn = m_properties->getValue("midi_input", ""); - juce::String midiOut = m_properties->getValue("midi_output", ""); + int xPosMargin = 10; + + //Inputs + addAndMakeVisible(m_inputMode); + m_inputMode.setBounds(1488 + xPosMargin - comboBox3Width/2, 821 - comboBox3Height/2, comboBox3Width, comboBox3Height); + addAndMakeVisible(m_inputSelect); + m_inputSelect.setBounds(1488 + xPosMargin - comboBox3Width/2, 921 - comboBox3Height/2, comboBox3Width, comboBox3Height); + + _parameterBinding.bind(m_inputMode, Virus::Param_InputMode); + _parameterBinding.bind(m_inputSelect, Virus::Param_InputSelect); + + //Arpeggiator + constexpr auto y = 18; + for (auto *s : {&m_globalTempo, &m_noteLength, &m_noteSwing}) + setupRotary(*this, *s); - if (midiIn != "") - { - processorRef.setMidiInput(midiIn); - } - if (midiOut != "") - { - processorRef.setMidiOutput(midiOut); - } + m_globalTempo.setBounds(1970 - knobSize / 2, 613 - knobSize / 2, knobSize, knobSize); + m_noteLength.setBounds(1424 - knobSize / 2, 613 - knobSize / 2, knobSize, knobSize); + m_noteSwing.setBounds(1574 - knobSize / 2, 613 - knobSize / 2, knobSize, knobSize); - m_cmbMidiInput.setBounds(1515 - 250 / 2, 827 - 47 / 2, 250, 47); - m_cmbMidiOutput.setBounds(1515 - 250 / 2, 926 - 47 / 2, 250, 47); + for (auto *c : {&m_mode, &m_pattern, &m_octaveRange, &m_resolution}) + addAndMakeVisible(c); - addAndMakeVisible(m_cmbMidiInput); - addAndMakeVisible(m_cmbMidiOutput); + m_mode.setBounds(1228 + xPosMargin - comboBox3Width/2, 558 - comboBox3Height/2, comboBox3Width, comboBox3Height); + m_pattern.setBounds(1228 + xPosMargin - comboBox3Width/2, 656 - comboBox3Height/2, comboBox3Width, comboBox3Height); + m_resolution.setBounds(1773 + xPosMargin - comboBox3Width/2, 656 - comboBox3Height/2, comboBox3Width, comboBox3Height); + m_octaveRange.setBounds(1773 + xPosMargin - comboBox3Width/2, 558 - comboBox3Height/2, comboBox3Width, comboBox3Height); - m_cmbMidiInput.setTextWhenNoChoicesAvailable("No MIDI Inputs Enabled"); - auto midiInputs = juce::MidiInput::getAvailableDevices(); - juce::StringArray midiInputNames; - midiInputNames.add(" - Midi In - "); - auto inIndex = 0; + addAndMakeVisible(m_arpHold); - for (int i = 0; i < midiInputs.size(); i++) - { - const auto input = midiInputs[i]; - if (processorRef.getMidiInput() != nullptr && input.identifier == processorRef.getMidiInput()->getIdentifier()) - { - inIndex = i + 1; - } - midiInputNames.add(input.name); - } + m_arpHold.setBounds(2129 - m_arpHold.kWidth/ 2, 613 - m_arpHold.kHeight / 2, m_arpHold.kWidth, m_arpHold.kHeight); + m_globalTempo.setEnabled(false); + m_globalTempo.setAlpha(0.3f); - m_cmbMidiInput.addItemList(midiInputNames, 1); - m_cmbMidiInput.setSelectedItemIndex(inIndex, juce::dontSendNotification); - m_cmbMidiOutput.setTextWhenNoChoicesAvailable("No MIDI Outputs Enabled"); - auto midiOutputs = juce::MidiOutput::getAvailableDevices(); - juce::StringArray midiOutputNames; - midiOutputNames.add(" - Midi Out - "); - auto outIndex = 0; + _parameterBinding.bind(m_globalTempo, Virus::Param_ClockTempo, 0); + _parameterBinding.bind(m_noteLength, Virus::Param_ArpNoteLength); + _parameterBinding.bind(m_noteSwing, Virus::Param_ArpSwing); + _parameterBinding.bind(m_mode, Virus::Param_ArpMode); + _parameterBinding.bind(m_pattern, Virus::Param_ArpPatternSelect); + _parameterBinding.bind(m_octaveRange, Virus::Param_ArpOctaveRange); + _parameterBinding.bind(m_resolution, Virus::Param_ArpClock); + _parameterBinding.bind(m_arpHold, Virus::Param_ArpHoldEnable); + + //SoftKnobs + m_softknobFunc1.setBounds(1756 + xPosMargin - comboBox3Width/2, 822 - comboBox3Height/2, comboBox3Width, comboBox3Height); + m_softknobFunc2.setBounds(1756 + xPosMargin - comboBox3Width/2, 921 - comboBox3Height/2, comboBox3Width, comboBox3Height); + m_softknobName1.setBounds(1983 + xPosMargin - comboBox3Width/2, 822 - comboBox3Height/2, comboBox3Width, comboBox3Height); + m_softknobName2.setBounds(1983 + xPosMargin - comboBox3Width/2, 921 - comboBox3Height/2, comboBox3Width, comboBox3Height); - for (int i = 0; i < midiOutputs.size(); i++) - { - const auto output = midiOutputs[i]; - if (processorRef.getMidiOutput() != nullptr && - output.identifier == processorRef.getMidiOutput()->getIdentifier()) - { - outIndex = i + 1; - } - midiOutputNames.add(output.name); - } + for (auto *c : {&m_softknobFunc1, &m_softknobFunc2, &m_softknobName1, &m_softknobName2}) + addAndMakeVisible(c); - m_cmbMidiOutput.addItemList(midiOutputNames, 1); - m_cmbMidiOutput.setSelectedItemIndex(outIndex, juce::dontSendNotification); - m_cmbMidiInput.onChange = [this]() { updateMidiInput(m_cmbMidiInput.getSelectedItemIndex()); }; - m_cmbMidiOutput.onChange = [this]() { updateMidiOutput(m_cmbMidiOutput.getSelectedItemIndex()); }; + _parameterBinding.bind(m_softknobName1, Virus::Param_SoftKnob1ShortName); + _parameterBinding.bind(m_softknobName2, Virus::Param_SoftKnob2ShortName); + _parameterBinding.bind(m_softknobFunc1, Virus::Param_SoftKnob1Single); + _parameterBinding.bind(m_softknobFunc2, Virus::Param_SoftKnob2Single); + + //PatchSettings + for (auto *s : {&m_patchVolume, &m_panning, &m_outputBalance, &m_transpose}) + setupRotary(*this, *s); + + for (auto *c : {&m_patchVolume, &m_panning, &m_outputBalance, &m_transpose}) + addAndMakeVisible(c); + + m_patchVolume.setBounds(1428 - knobSize / 2, 113 - knobSize / 2, knobSize, knobSize); + m_panning.setBounds(1572 - knobSize / 2, 113 - knobSize / 2, knobSize, knobSize); + m_outputBalance.setBounds(1715 - knobSize / 2, 113 - knobSize / 2, knobSize, knobSize); + m_transpose.setBounds(1862 - knobSize / 2, 113 - knobSize / 2, knobSize, knobSize); + + for (auto *c : {&m_keyMode, &m_bendUp, &m_bendDown, &m_bendScale, &m_smoothMode, &m_cat1, &m_cat2}) + addAndMakeVisible(c); + + m_keyMode.setBounds(1232 + xPosMargin - comboBox3Width/2, 113 - comboBox3Height/2, comboBox3Width, comboBox3Height); + m_smoothMode.setBounds(1232 + xPosMargin - comboBox3Width/2, 259 - comboBox3Height/2, comboBox3Width, comboBox3Height); + m_bendScale.setBounds(1436 + xPosMargin - comboBox3Width/2, 259 - comboBox3Height/2, comboBox3Width, comboBox3Height); + m_bendUp.setBounds(1641 + xPosMargin - comboBox3Width/2, 259 - comboBox3Height/2, comboBox3Width, comboBox3Height); + m_bendDown.setBounds(1848 + xPosMargin - comboBox3Width/2, 259 - comboBox3Height/2, comboBox3Width, comboBox3Height); + + m_cat1.setBounds(1232 + xPosMargin - comboBox3Width/2, 382 - comboBox3Height/2, comboBox3Width, comboBox3Height); + m_cat2.setBounds(1436 + xPosMargin - comboBox3Width/2, 382 - comboBox3Height/2, comboBox3Width, comboBox3Height); + _parameterBinding.bind(m_patchVolume, Virus::Param_PatchVolume); + _parameterBinding.bind(m_panning, Virus::Param_Panorama); + //_parameterBinding.bind(m_outputBalance, Virus::Param_SecondOutputBalance); + _parameterBinding.bind(m_transpose, Virus::Param_Transpose); + _parameterBinding.bind(m_keyMode, Virus::Param_KeyMode); + _parameterBinding.bind(m_bendUp, Virus::Param_BenderRangeUp); + _parameterBinding.bind(m_bendDown, Virus::Param_BenderRangeDown); + _parameterBinding.bind(m_bendScale, Virus::Param_BenderScale); + _parameterBinding.bind(m_smoothMode, Virus::Param_ControlSmoothMode); + _parameterBinding.bind(m_cat1, Virus::Param_Category1); + _parameterBinding.bind(m_cat2, Virus::Param_Category2); + _parameterBinding.bind(m_secondaryOutput, Virus::Param_PartOutputSelect); + //Channels int iMarginYChannels = 118; int iMarginXChannels = 0; int iIndex = 0; - //Channels for (auto pt = 0; pt < 16; pt++) { if (pt==8) @@ -95,59 +129,13 @@ ArpEditor::ArpEditor(VirusParameterBinding &_parameterBinding, AudioPluginAudioP m_partSelect[pt].onClick = [this, pt]() {this->changePart(pt);}; addAndMakeVisible(m_partSelect[pt]); - m_presetNames[pt].setBounds(195 - 120/2 + iMarginXChannels, 104 - 50/2 + iIndex * (iMarginYChannels), 120, 38); + m_presetNames[pt].setBounds(245 - 225/2 + iMarginXChannels, 97 - 70/2 + iIndex * (iMarginYChannels), 225, 70); m_presetNames[pt].setText(m_controller.getCurrentPartPresetName(pt), juce::dontSendNotification); - m_presetNames[pt].setFont(juce::Font("Arial", "Normal", 20.f)); - m_presetNames[pt].setColour(juce::Label::ColourIds::textColourId,juce::Colours::red); - - addAndMakeVisible(m_PresetPatch[pt]); - m_PresetPatch[pt].setBounds(275 - m_PresetPatch[pt].kWidth / 2 + iMarginXChannels, 96 - m_PresetPatch[pt].kHeight / 2 + iIndex * (iMarginYChannels), m_PresetPatch[pt].kWidth, m_PresetPatch[pt].kHeight); - //m_PresetPatchList.onClick = [this]() {ShowMenuePatchList(); }; - - m_PresetPatch[pt].onClick = [this, pt]() { - juce::PopupMenu selector; - - for (uint8_t b = 0; b < m_controller.getBankCount(); ++b) - { - const auto bank = virusLib::fromArrayIndex(b); - auto presetNames = m_controller.getSinglePresetNames(bank); - juce::PopupMenu p; - for (uint8_t j = 0; j < 128; j++) - { - const auto presetName = presetNames[j]; - p.addItem(presetNames[j], [this, bank, j, pt, presetName] { - m_controller.setCurrentPartPreset(pt, bank, j); - m_PresetPatch[pt].setButtonText(presetName); - getParentComponent()->postCommandMessage(VirusEditor::Commands::UpdateParts); - }); - } - std::stringstream bankName; - bankName << "Bank " << static_cast<char>('A' + b); - selector.addSubMenu(std::string(bankName.str()), p); - } - selector.showMenu(juce::PopupMenu::Options()); - }; + m_presetNames[pt].setFont(juce::Font("Register", "Normal", 23.f)); + m_presetNames[pt].setJustificationType(Justification::left); + addAndMakeVisible(m_presetNames[pt]); - - m_prevPatch[pt].setBounds(307 - m_prevPatch[pt].kWidth / 2 + iMarginXChannels, 96 - m_prevPatch[pt].kHeight / 2 + iIndex * (iMarginYChannels), m_prevPatch[pt].kWidth, m_prevPatch[pt].kHeight); - m_nextPatch[pt].setBounds(340 - m_nextPatch[pt].kWidth / 2 + iMarginXChannels, 96 - m_nextPatch[pt].kHeight / 2 + iIndex * (iMarginYChannels), m_nextPatch[pt].kWidth, m_nextPatch[pt].kHeight); - - m_prevPatch[pt].onClick = [this, pt]() - { - m_controller.setCurrentPartPreset(pt, m_controller.getCurrentPartBank(pt),std::max(0, m_controller.getCurrentPartProgram(pt) - 1)); - getParentComponent()->postCommandMessage(VirusEditor::Commands::UpdateParts); - }; - - m_nextPatch[pt].onClick = [this, pt]() - { - m_controller.setCurrentPartPreset(pt, m_controller.getCurrentPartBank(pt),std::min(127, m_controller.getCurrentPartProgram(pt) + 1)); - getParentComponent()->postCommandMessage(VirusEditor::Commands::UpdateParts); - }; - - addAndMakeVisible(m_prevPatch[pt]); - addAndMakeVisible(m_nextPatch[pt]); - //Knobs for (auto *s : {&m_partVolumes[pt], &m_partPans[pt]}) { @@ -182,7 +170,10 @@ ArpEditor::ArpEditor(VirusParameterBinding &_parameterBinding, AudioPluginAudioP updatePlayModeButtons(); }; + m_partSelect[m_controller.getCurrentPart()].setToggleState(true, NotificationType::dontSendNotification); refreshParts(); + + MidiInit(); } ArpEditor::~ArpEditor() @@ -194,6 +185,69 @@ ArpEditor::~ArpEditor() } } +void ArpEditor::MidiInit() +{ + //MIDI settings + juce::String midiIn = m_properties->getValue("midi_input", ""); + juce::String midiOut = m_properties->getValue("midi_output", ""); + + if (midiIn != "") + { + processorRef.setMidiInput(midiIn); + } + if (midiOut != "") + { + processorRef.setMidiOutput(midiOut); + } + + m_cmbMidiInput.setBounds(2138 - 250 / 2, 81 - 47 / 2, 250, 47); + m_cmbMidiOutput.setBounds(2138 - 250 / 2, 178 - 47 / 2, 250, 47); + + addAndMakeVisible(m_cmbMidiInput); + addAndMakeVisible(m_cmbMidiOutput); + + m_cmbMidiInput.setTextWhenNoChoicesAvailable("No MIDI Inputs Enabled"); + auto midiInputs = juce::MidiInput::getAvailableDevices(); + juce::StringArray midiInputNames; + midiInputNames.add(" - Midi In - "); + auto inIndex = 0; + + for (int i = 0; i < midiInputs.size(); i++) + { + const auto input = midiInputs[i]; + if (processorRef.getMidiInput() != nullptr && input.identifier == processorRef.getMidiInput()->getIdentifier()) + { + inIndex = i + 1; + } + midiInputNames.add(input.name); + } + + m_cmbMidiInput.addItemList(midiInputNames, 1); + m_cmbMidiInput.setSelectedItemIndex(inIndex, juce::dontSendNotification); + m_cmbMidiOutput.setTextWhenNoChoicesAvailable("No MIDI Outputs Enabled"); + auto midiOutputs = juce::MidiOutput::getAvailableDevices(); + juce::StringArray midiOutputNames; + midiOutputNames.add(" - Midi Out - "); + auto outIndex = 0; + + for (int i = 0; i < midiOutputs.size(); i++) + { + const auto output = midiOutputs[i]; + if (processorRef.getMidiOutput() != nullptr && + output.identifier == processorRef.getMidiOutput()->getIdentifier()) + { + outIndex = i + 1; + } + midiOutputNames.add(output.name); + } + + m_cmbMidiOutput.addItemList(midiOutputNames, 1); + m_cmbMidiOutput.setSelectedItemIndex(outIndex, juce::dontSendNotification); + m_cmbMidiInput.onChange = [this]() { updateMidiInput(m_cmbMidiInput.getSelectedItemIndex()); }; + m_cmbMidiOutput.onChange = [this]() { updateMidiOutput(m_cmbMidiOutput.getSelectedItemIndex()); }; +} + + void ArpEditor::refreshParts() { const auto multiMode = m_controller.isMultiMode(); @@ -208,16 +262,10 @@ void ArpEditor::refreshParts() m_partVolumes[pt].setAlpha(fAlpha); m_partPans[pt].setEnabled(singlePartOrInMulti); m_partPans[pt].setAlpha(fAlpha); - m_PresetPatch[pt].setEnabled(singlePartOrInMulti); - m_PresetPatch[pt].setAlpha(fAlpha); m_partSelect[pt].setEnabled(singlePartOrInMulti); m_partSelect[pt].setAlpha(fAlpha); m_presetNames[pt].setEnabled(singlePartOrInMulti); m_presetNames[pt].setAlpha(fAlpha); - m_prevPatch[pt].setEnabled(singlePartOrInMulti); - m_prevPatch[pt].setAlpha(fAlpha); - m_nextPatch[pt].setEnabled(singlePartOrInMulti); - m_nextPatch[pt].setAlpha(fAlpha); } if (singlePartOrInMulti) m_presetNames[pt].setText(m_controller.getCurrentPartPresetName(pt), juce::dontSendNotification); @@ -242,7 +290,6 @@ void ArpEditor::changePart(uint8_t _part) void ArpEditor::setPlayMode(uint8_t _mode) { - m_controller.getParameter(Virus::Param_PlayMode)->setValue(_mode); if (_mode == virusLib::PlayModeSingle && m_controller.getCurrentPart() != 0) { diff --git a/source/jucePlugin/ui2/Virus_Panel4_ArpEditor.h b/source/jucePlugin/ui2/Virus_Panel4_ArpEditor.h @@ -18,6 +18,7 @@ public: private: void updateMidiInput(int index); void updateMidiOutput(int index); + void MidiInit(); Virus::LookAndFeelSmallButton m_lookAndFeelSmallButton; //WorkingMode @@ -32,10 +33,10 @@ private: Buttons::Button3 m_partSelect[16]; //juce::Label m_partLabels[16]; - Buttons::PresetButtonDown m_PresetPatch[16]; + //Buttons::PresetButtonDown m_PresetPatch[16]; juce::Label m_presetNames[16]; - Buttons::PresetButtonRight m_nextPatch[16]; - Buttons::PresetButtonLeft m_prevPatch[16]; + //Buttons::PresetButtonRight m_nextPatch[16]; + //Buttons::PresetButtonLeft m_prevPatch[16]; juce::Slider m_partVolumes[16]; juce::Slider m_partPans[16]; @@ -59,7 +60,7 @@ private: Buttons::Button3 m_arpHold; //SoftKnobs - juce::ComboBox m_softknob1, m_softknob2; + juce::ComboBox m_softknobFunc1, m_softknobFunc2, m_softknobName1, m_softknobName2; //PatchSettings juce::Slider m_patchVolume, m_panning, m_outputBalance, m_transpose; diff --git a/source/jucePlugin/ui2/Virus_Panel5_PatchBrowser.cpp b/source/jucePlugin/ui2/Virus_Panel5_PatchBrowser.cpp @@ -72,7 +72,8 @@ PatchBrowser::PatchBrowser(VirusParameterBinding & _parameterBinding, AudioPlugi m_filteredPatches.add(patch); } else if(patch.name.containsIgnoreCase(searchValue)) { - m_filteredPatches.add(patch); + if (patch.name!="") + m_filteredPatches.add(patch); } } m_patchList.updateContent(); @@ -90,21 +91,23 @@ PatchBrowser::PatchBrowser(VirusParameterBinding & _parameterBinding, AudioPlugi m_ROMBankSelect.setBounds(510 - 961 / 2, 78 - 51 / 2, 961, 51); for (int i=1; i<=m_controller.getBankCount()-1;i++) { - m_ROMBankSelect.addItem("BANK: " + getCurrentPartBankStr((virusLib::BankNumber)i),i); + m_ROMBankSelect.addItem("BANK: " + getCurrentPartBankStr((virusLib::BankNumber)i),i+1); } m_ROMBankSelect.onChange = [this]() { - m_selectedBankNo = m_ROMBankSelect.getSelectedItemIndex() + 1; - LoadBankNr(m_selectedBankNo); - bIsFileMode = false; + m_LastBankRomNoUsed = m_ROMBankSelect.getSelectedItemIndex()+1; + //m_LastPatchNoUsed = 0; + LoadBankNr(m_LastBankRomNoUsed); + m_bIsFileMode = false; m_search.setText("", true); + getParentComponent()->postCommandMessage(VirusEditor::Commands::SelectFirstPatch); + getParentComponent()->postCommandMessage(VirusEditor::Commands::UpdateParts); + SaveSettings(); }; m_SavePreset.setBounds(2197 - m_SavePreset.kWidth / 2, 72 - m_SavePreset.kHeight / 2, m_SavePreset.kWidth, m_SavePreset.kHeight); m_SavePreset.onClick = [this]() { savePreset(); }; - - bIsFileMode=true; } PatchBrowser::~PatchBrowser() @@ -113,17 +116,62 @@ PatchBrowser::~PatchBrowser() m_bankList.setLookAndFeel(nullptr); } +void PatchBrowser::IntiPatches() +{ + //Read Last Patch used from config file + //m_LastPatchNoUsed = m_properties->getIntValue("last_patch_no_used", 1) - 1; + m_bIsFileMode = m_properties->getBoolValue("is_file_used", false); + m_LastBankRomNoUsed = m_properties->getIntValue("last_bank_rom_no_used", 1); + m_LastFileUsed = m_properties->getValue("last_file_used", ""); + + if(!m_bIsFileMode) + { + m_ROMBankSelect.setSelectedItemIndex(m_LastBankRomNoUsed-1, dontSendNotification); + LoadBankNr(m_LastBankRomNoUsed); + m_search.setText("", true); + //getParentComponent()->postCommandMessage(VirusEditor::Commands::SelectFirstPatch); + } + else + { + m_bankList.setFileName(m_LastFileUsed); + m_bankList.selectionChanged(); + const juce::File &file(m_LastFileUsed); + LoadPatchesFromFile(file); + } + + //getParentComponent()->postCommandMessage(VirusEditor::Commands::SelectFirstPatch); + //getParentComponent()->postCommandMessage(VirusEditor::Commands::UpdateParts); + + //m_patchList.selectRow(m_LastPatchNoUsed,true,true); + //getParentComponent()->postCommandMessage(VirusEditor::Commands::UpdateParts); +} + +void PatchBrowser::SaveSettings() +{ + m_properties->setValue("last_file_used", m_LastFileUsed); + //m_properties->setValue("last_patch_no_used", m_LastPatchNoUsed+1); + m_properties->setValue("is_file_used", m_bIsFileMode); + m_properties->setValue("last_bank_rom_no_used", m_LastBankRomNoUsed); + m_properties->save(); +} + + +bool PatchBrowser::GetIsFileMode() +{ + return m_bIsFileMode; +} + void PatchBrowser::selectionChanged() {} void PatchBrowser::LoadBankNr(int iBankNo) { - juce::StringArray patches = m_controller.getSinglePresetNames((virusLib::BankNumber)(m_selectedBankNo)); + juce::StringArray patches = m_controller.getSinglePresetNames((virusLib::BankNumber)(iBankNo)); m_patches.clear(); for (int i=0 ; i<128 ; i++) - { + { Patch patch; - patch.progNumber = i+1; + patch.progNumber = i; //data.copyTo(patch.data, 267*index + 9, 256); patch.name = patches.strings[i]; patch.category1 = 0; @@ -144,7 +192,6 @@ void PatchBrowser::LoadBankNr(int iBankNo) m_filteredPatches.add(patch); } } - m_patchList.updateContent(); m_patchList.deselectAllRows(); m_patchList.repaint(); @@ -291,6 +338,8 @@ void PatchBrowser::fileClicked(const juce::File &file, const juce::MouseEvent &e { auto ext = file.getFileExtension().toLowerCase(); auto path = file.getParentDirectory().getFullPathName(); + + //Show popup only on directory if (file.isDirectory() && e.mods.isRightButtonDown()) { auto p = juce::PopupMenu(); p.addItem("Add directory contents to patch list", [this, file]() { @@ -312,41 +361,54 @@ void PatchBrowser::fileClicked(const juce::File &file, const juce::MouseEvent &e } m_patchList.updateContent(); m_patchList.deselectAllRows(); - m_patchList.repaint(); + m_patchList.repaint(); }); p.showMenu(juce::PopupMenu::Options()); return; } + m_properties->setValue("virus_bank_dir", path); + if(file.existsAsFile() && ext == ".syx" || ext == ".midi" || ext == ".mid") { - m_patches.clear(); - loadBankFile(file); - m_filteredPatches.clear(); - for(auto patch : m_patches) { - const auto searchValue = m_search.getText(); - if (searchValue.isEmpty()) { - m_filteredPatches.add(patch); - } - else if(patch.name.containsIgnoreCase(searchValue)) { - m_filteredPatches.add(patch); - } - } - m_patchList.updateContent(); - m_patchList.deselectAllRows(); - m_patchList.repaint(); + LoadPatchesFromFile(file); + m_LastFileUsed = file.getFullPathName(); } - bIsFileMode = true; + m_bIsFileMode = true; m_search.setText("", true); + m_ROMBankSelect.setText("",true); + SaveSettings(); + getParentComponent()->postCommandMessage(VirusEditor::Commands::SelectFirstPatch); + getParentComponent()->postCommandMessage(VirusEditor::Commands::UpdateParts); } +void PatchBrowser::LoadPatchesFromFile(const juce::File &file) +{ + m_patches.clear(); + loadBankFile(file); + m_filteredPatches.clear(); + for(auto patch : m_patches) { + const auto searchValue = m_search.getText(); + if (searchValue.isEmpty()) { + m_filteredPatches.add(patch); + } + else if(patch.name.containsIgnoreCase(searchValue)) { + m_filteredPatches.add(patch); + } + } + m_patchList.updateContent(); + m_patchList.deselectAllRows(); + m_patchList.repaint(); +} + + void PatchBrowser::fileDoubleClicked(const juce::File &file) {} void PatchBrowser::browserRootChanged(const File &newRoot) {} int PatchBrowser::getNumRows() { - return m_patches.size(); + return m_filteredPatches.size(); } void PatchBrowser::paintRowBackground(Graphics &g, int rowNumber, int width, int height, bool rowIsSelected) @@ -370,10 +432,10 @@ void PatchBrowser::paintCell(Graphics &g, int rowNumber, int columnId, int width //auto text = rowElement.name; juce::String text = ""; - if (bIsFileMode) + if (m_bIsFileMode) { if (columnId == ColumnsPatch::INDEX) - text = juce::String(rowElement.progNumber); + text = juce::String(rowElement.progNumber+1); else if (columnId == ColumnsPatch::NAME) text = rowElement.name; else if (columnId == ColumnsPatch::CAT1) @@ -394,7 +456,7 @@ void PatchBrowser::paintCell(Graphics &g, int rowNumber, int columnId, int width else { if (columnId == ColumnsPatch::INDEX) - text = juce::String(rowElement.progNumber); + text = juce::String(rowElement.progNumber+1); else if (columnId == ColumnsPatch::NAME) text = rowElement.name; } @@ -406,14 +468,13 @@ void PatchBrowser::paintCell(Graphics &g, int rowNumber, int columnId, int width } - void PatchBrowser::selectedRowsChanged(int lastRowSelected) { auto idx = m_patchList.getSelectedRow(); if (idx == -1) { return; } - if (bIsFileMode) + if (m_bIsFileMode) { uint8_t syxHeader[9] = {0xF0, 0x00, 0x20, 0x33, 0x01, 0x00, 0x10, 0x00, 0x00}; syxHeader[8] = m_controller.isMultiMode() ? m_controller.getCurrentPart() : virusLib::ProgramType::SINGLE; // set edit buffer @@ -443,8 +504,11 @@ void PatchBrowser::selectedRowsChanged(int lastRowSelected) { } else { - m_controller.setCurrentPartPreset(m_controller.getCurrentPart(), (virusLib::BankNumber) m_selectedBankNo, m_filteredPatches[idx].progNumber-1); - } + m_controller.setCurrentPartPreset(m_controller.getCurrentPart(), (virusLib::BankNumber) m_LastBankRomNoUsed, m_filteredPatches[idx].progNumber); + getParentComponent()->postCommandMessage(VirusEditor::Commands::UpdateParts); + } + + //m_LastPatchNoUsed = m_filteredPatches[idx].progNumber; } void PatchBrowser::cellDoubleClicked(int rowNumber, int columnId, const juce::MouseEvent &) @@ -548,7 +612,6 @@ void PatchBrowser::loadBankFileToRom(const juce::File &file) if (sentData) { - //Load first patch m_controller.onStateLoaded(); } } diff --git a/source/jucePlugin/ui2/Virus_Panel5_PatchBrowser.h b/source/jucePlugin/ui2/Virus_Panel5_PatchBrowser.h @@ -38,7 +38,9 @@ public: void loadFile(); void loadBankFileToRom(const juce::File &file); void savePreset(); - + bool GetIsFileMode(); + juce::TableListBox m_patchList; + void IntiPatches(); private: Virus::LookAndFeelPatchBrowser m_landf; @@ -58,7 +60,7 @@ private: juce::WildcardFileFilter m_fileFilter; juce::FileBrowserComponent m_bankList; - juce::TableListBox m_patchList; + //juce::TableListBox m_romBankList; juce::TextEditor m_search; juce::Array<Patch> m_patches; @@ -72,11 +74,16 @@ private: //Buttons::Button2 m_btModeRomFile; void LoadBankNr(int iBankNo); - int m_selectedBankNo; - juce::ComboBox m_ROMBankSelect; - bool bIsFileMode; + void SaveSettings(); + void LoadPatchesFromFile(const juce::File &file); + juce::ComboBox m_ROMBankSelect; juce::String m_previousPath; + juce::String m_LastFileUsed; + //int m_LastPatchNoUsed; + int m_LastBankRomNoUsed; + + bool m_bIsFileMode; // Inherited via FileBrowserListener void selectionChanged() override;