gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

commit 1a6b04af89b3aa4cd0faede7e9da5d90956d3aba
parent 51d0db4fc56a1125e43ff1ab0360112355f4344d
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Mon, 14 Mar 2022 23:13:37 +0100

begin generic UI for Virus implementation

Diffstat:
Msource/jucePlugin/CMakeLists.txt | 12+++++++++++-
Msource/jucePlugin/PluginEditor.cpp | 3++-
Asource/jucePlugin/ui3/Parts.cpp | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asource/jucePlugin/ui3/Parts.h | 39+++++++++++++++++++++++++++++++++++++++
Asource/jucePlugin/ui3/Tabs.cpp | 0
Asource/jucePlugin/ui3/Tabs.h | 13+++++++++++++
Asource/jucePlugin/ui3/VirusEditor.cpp | 12++++++++++++
Asource/jucePlugin/ui3/VirusEditor.h | 20++++++++++++++++++++
8 files changed, 239 insertions(+), 2 deletions(-)

diff --git a/source/jucePlugin/CMakeLists.txt b/source/jucePlugin/CMakeLists.txt @@ -73,6 +73,15 @@ set(SOURCES_UI2 ui2/VirusEditor.h ) +set(SOURCES_UI3 + ui3/Parts.cpp + ui3/Parts.h + ui3/Tabs.cpp + ui3/Tabs.h + ui3/VirusEditor.cpp + ui3/VirusEditor.h +) + set(SOURCES_GENERICUI genericUI/editor.cpp genericUI/editor.h genericUI/image.cpp genericUI/image.h @@ -168,11 +177,12 @@ macro(createJucePlugin targetName productName isSynth plugin4CC binaryDataProjec PRODUCT_NAME ${productName} # The name of the final executable, which can differ from the target name ) - target_sources(${targetName} PRIVATE ${SOURCES} ${SOURCES_UI} ${SOURCES_UI2} ${SOURCES_GENERICUI}) + target_sources(${targetName} PRIVATE ${SOURCES} ${SOURCES_UI} ${SOURCES_UI2} ${SOURCES_UI3} ${SOURCES_GENERICUI}) source_group("source" FILES ${SOURCES}) source_group("source\\ui" FILES ${SOURCES_UI}) source_group("source\\ui2" FILES ${SOURCES_UI2}) + source_group("source\\ui3" FILES ${SOURCES_UI3}) source_group("source\\genericUI" FILES ${SOURCES_GENERICUI}) target_compile_definitions(${targetName} diff --git a/source/jucePlugin/PluginEditor.cpp b/source/jucePlugin/PluginEditor.cpp @@ -7,6 +7,7 @@ #include "ui/VirusEditor.h" #include "ui2/VirusEditor.h" +#include "ui3/VirusEditor.h" //============================================================================== AudioPluginAudioProcessorEditor::AudioPluginAudioProcessorEditor(AudioPluginAudioProcessor &p) : @@ -79,7 +80,7 @@ void AudioPluginAudioProcessorEditor::LoadSkin(int index) { { try { - m_virusEditor.reset(new genericUI::Editor(std::string(BinaryData::VirusC_json), m_parameterBinding, processorRef.getController())); + m_virusEditor.reset(new genericVirusUI::VirusEditor(m_parameterBinding, processorRef.getController())); setSize(m_virusEditor->getWidth(), m_virusEditor->getHeight()); } catch(const std::runtime_error& _err) diff --git a/source/jucePlugin/ui3/Parts.cpp b/source/jucePlugin/ui3/Parts.cpp @@ -0,0 +1,142 @@ +#include "Parts.h" + +#include "VirusEditor.h" +#include "../VirusController.h" +#include "../VirusParameterBinding.h" +#include "dsp56kEmu/logging.h" + +namespace genericVirusUI +{ + Parts::Parts(VirusEditor& _editor) : m_editor(_editor) + { + _editor.findComponents<juce::Button>(m_partSelect, "SelectPart"); + _editor.findComponents<juce::Button>(m_presetPrev, "PresetPrev"); + _editor.findComponents<juce::Button>(m_presetNext, "PresetNext"); + + _editor.findComponents<juce::Slider>(m_partVolume, "PartVolume"); + _editor.findComponents<juce::Slider>(m_partPan, "PartPan"); + _editor.findComponents<juce::TextButton>(m_presetName, "PresetName"); + + for(size_t i=0; i<m_partSelect.size(); ++i) + { + m_partSelect[i]->onClick = [this, i]{ selectPart(i); }; + m_presetPrev[i]->onClick = [this, i]{ selectPrevPreset(i); }; + m_presetNext[i]->onClick = [this, i]{ selectNextPreset(i); }; + m_presetName[i]->onClick = [this, i]{ selectPreset(i); }; + + _editor.getParameterBinding().bind(*m_partVolume[i], Virus::Param_PartVolume, static_cast<uint8_t>(i)); + _editor.getParameterBinding().bind(*m_partPan[i], Virus::Param_Panorama, static_cast<uint8_t>(i)); + } + + updateAll(); + + m_editor.getController().onProgramChange = [this] + { + updateAll(); + }; + } + + Parts::~Parts() + { + m_editor.getController().onProgramChange = nullptr; + } + + void Parts::selectPart(const size_t _part) + { + m_editor.getController().setCurrentPart(static_cast<uint8_t>(_part)); + } + + void Parts::selectPrevPreset(const size_t _part) + { + Virus::Controller& controller = m_editor.getController(); + + const auto pt = static_cast<uint8_t>(_part); + + if(controller.getCurrentPartProgram(pt) > 0) + { + controller.setCurrentPartPreset(pt, controller.getCurrentPartBank(pt), controller.getCurrentPartProgram(pt) - 1); + } + } + + void Parts::selectNextPreset(const size_t _part) + { + Virus::Controller& controller = m_editor.getController(); + + const auto pt = static_cast<uint8_t>(_part); + if(controller.getCurrentPartProgram(pt) < 127) // FIXME: magic value + { + controller.setCurrentPartPreset(pt, controller.getCurrentPartBank(pt), controller.getCurrentPartProgram(pt) + 1); + } + } + + void Parts::selectPreset(size_t _part) + { + juce::PopupMenu selector; + + const auto pt = static_cast<uint8_t>(_part); + + for (uint8_t b = 0; b < m_editor.getController().getBankCount(); ++b) + { + const auto bank = virusLib::fromArrayIndex(b); + auto presetNames = m_editor.getController().getSinglePresetNames(bank); + juce::PopupMenu p; + for (uint8_t j = 0; j < presetNames.size(); j++) + { + const auto presetName = presetNames[j]; + p.addItem(presetNames[j], [this, bank, j, pt, presetName] + { + m_editor.getController().setCurrentPartPreset(pt, bank, j); + }); + } + std::stringstream bankName; + bankName << "Bank " << static_cast<char>('A' + b); + selector.addSubMenu(std::string(bankName.str()), p); + } + selector.showMenuAsync(juce::PopupMenu::Options()); + } + + void Parts::updatePresetNames() + { + for(size_t i=0; i<m_presetName.size(); ++i) + m_presetName[i]->setButtonText(m_editor.getController().getCurrentPartPresetName(static_cast<uint8_t>(i))); + } + + void Parts::updateSelectedPart() + { + const auto part = m_editor.getController().getCurrentPart(); + + if(part < m_partSelect.size()) + m_partSelect[part]->setToggleState(true, juce::dontSendNotification); + + for(size_t i=0; i<m_partSelect.size(); ++i) + { + if(i == part) + continue; + m_partSelect[i]->setToggleState(false, juce::dontSendNotification); + } + } + + void Parts::updateSingleOrMultiMode() + { + const auto multiMode = m_editor.getController().isMultiMode(); + + for(size_t i=0; i<m_partSelect.size(); ++i) + { + const bool visible = multiMode || !i; + + m_partSelect[i]->setVisible(visible); + m_partPan[i]->setVisible(visible); + m_partVolume[i]->setVisible(visible); + m_presetPrev[i]->setVisible(visible); + m_presetNext[i]->setVisible(visible); + m_presetName[i]->setVisible(visible); + } + } + + void Parts::updateAll() + { + updatePresetNames(); + updateSelectedPart(); + updateSingleOrMultiMode(); + } +} diff --git a/source/jucePlugin/ui3/Parts.h b/source/jucePlugin/ui3/Parts.h @@ -0,0 +1,39 @@ +#pragma once + +#include <vector> + +#include <juce_audio_processors/juce_audio_processors.h> + +namespace genericVirusUI +{ + class VirusEditor; + + class Parts + { + public: + explicit Parts(VirusEditor& _editor); + virtual ~Parts(); + + private: + void selectPart(size_t _part); + void selectPrevPreset(size_t _part); + void selectNextPreset(size_t _part); + void selectPreset(size_t _part); + + void updatePresetNames(); + void updateSelectedPart(); + void updateAll(); + void updateSingleOrMultiMode(); + + VirusEditor& m_editor; + + std::vector<juce::Button*> m_partSelect; + std::vector<juce::Button*> m_presetPrev; + std::vector<juce::Button*> m_presetNext; + + std::vector<juce::Slider*> m_partVolume; + std::vector<juce::Slider*> m_partPan; + + std::vector<juce::TextButton*> m_presetName; + }; +} diff --git a/source/jucePlugin/ui3/Tabs.cpp b/source/jucePlugin/ui3/Tabs.cpp diff --git a/source/jucePlugin/ui3/Tabs.h b/source/jucePlugin/ui3/Tabs.h @@ -0,0 +1,12 @@ +#pragma once + +namespace genericVirusUI +{ + class Tabs + { + public: + Tabs(VirusEditor& _editor) : m_editor(_editor) {} + private: + VirusEditor& m_editor; + }; +} +\ No newline at end of file diff --git a/source/jucePlugin/ui3/VirusEditor.cpp b/source/jucePlugin/ui3/VirusEditor.cpp @@ -0,0 +1,12 @@ +#include "VirusEditor.h" + +#include "BinaryData.h" + +namespace genericVirusUI +{ + VirusEditor::VirusEditor(VirusParameterBinding& _binding, Virus::Controller& _controller) : Editor(std::string(BinaryData::VirusC_json, BinaryData::VirusC_jsonSize), _binding, _controller), + m_parts(*this), + m_tabs(*this) + { + } +} diff --git a/source/jucePlugin/ui3/VirusEditor.h b/source/jucePlugin/ui3/VirusEditor.h @@ -0,0 +1,19 @@ +#pragma once + +#include "../genericUI/editor.h" + +#include "Parts.h" +#include "Tabs.h" + +namespace genericVirusUI +{ + class VirusEditor : public genericUI::Editor + { + public: + VirusEditor(VirusParameterBinding& _binding, Virus::Controller& _controller); + + private: + Parts m_parts; + Tabs m_tabs; + }; +} +\ No newline at end of file