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 1f64eb3af80f3ade2633eaba6edddefb824402b5
parent 095428891b5ce4465c05e46277b740f3fa870935
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Sat,  3 Dec 2022 18:21:50 +0100

preset prev/next buttons toggle browser presets if the current preset came from a browser selection

Diffstat:
Msource/jucePlugin/VirusController.cpp | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Msource/jucePlugin/VirusController.h | 29+++++++++++++++++++++++++----
Msource/jucePlugin/ui3/Parts.cpp | 21++++++---------------
Msource/jucePlugin/ui3/PatchBrowser.cpp | 42++++++++++++++++++++++++++++++++++++++++--
Msource/jucePlugin/ui3/PatchBrowser.h | 5+++++
Msource/jucePlugin/ui3/VirusEditor.cpp | 5+++++
Msource/jucePlugin/ui3/VirusEditor.h | 2++
7 files changed, 141 insertions(+), 41 deletions(-)

diff --git a/source/jucePlugin/VirusController.cpp b/source/jucePlugin/VirusController.cpp @@ -254,7 +254,7 @@ namespace Virus void Controller::setCurrentPartPreset(uint8_t _part, const virusLib::BankNumber _bank, uint8_t _prg) { - if(_bank == virusLib::BankNumber::EditBuffer || _prg > 127) + if(_bank == virusLib::BankNumber::EditBuffer || _prg > m_singles[0].size()) { jassertfalse; return; @@ -273,21 +273,33 @@ namespace Virus sendParameterChange(MessageType::PARAM_CHANGE_C, pt, virusLib::PART_BANK_SELECT, virusLib::toMidiByte(_bank)); sendParameterChange(MessageType::PARAM_CHANGE_C, pt, virusLib::PART_PROGRAM_CHANGE, _prg); - requestSingle(virusLib::toMidiByte(virusLib::BankNumber::EditBuffer), pt); + requestSingle(toMidiByte(virusLib::BankNumber::EditBuffer), pt); m_currentBank[_part] = _bank; m_currentProgram[_part] = _prg; + m_currentPresetSource[_part] = PresetSource::Rom; + } + + void Controller::setCurrentPartPresetSource(uint8_t _part, PresetSource _source) + { + m_currentPresetSource[_part] = _source; } virusLib::BankNumber Controller::getCurrentPartBank(const uint8_t _part) const { return m_currentBank[_part]; } + uint8_t Controller::getCurrentPartProgram(const uint8_t _part) const { return m_currentProgram[_part]; } + Controller::PresetSource Controller::getCurrentPartPresetSource(uint8_t _part) const + { + return m_currentPresetSource[_part]; + } + bool Controller::parseSingle(pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::ParamValues& _parameterValues, const SysEx& _msg) const { const auto packetName = midiPacketName(MidiPacketType::SingleDump); @@ -371,26 +383,36 @@ namespace Virus linkedParam->setValueFromSynth(it->second, true); } - bool found = false; - for(size_t b=0; b<m_singles.size() && !found; ++b) + if(m_currentPresetSource[ch] != PresetSource::Browser) { - const auto& singlePatches = m_singles[b]; - - for(size_t s=0; s<singlePatches.size(); ++s) - { - const auto& singlePatch = singlePatches[s]; - - if(singlePatch.name == patch.name) - { - m_currentBank[ch] = virusLib::fromArrayIndex(static_cast<uint8_t>(b)); - m_currentProgram[ch] = static_cast<uint8_t>(s); - found = true; - break; - } - } + bool found = false; + for(size_t b=0; b<m_singles.size() && !found; ++b) + { + const auto& singlePatches = m_singles[b]; + + for(size_t s=0; s<singlePatches.size(); ++s) + { + const auto& singlePatch = singlePatches[s]; + + if(singlePatch.name == patch.name) + { + m_currentBank[ch] = virusLib::fromArrayIndex(static_cast<uint8_t>(b)); + m_currentProgram[ch] = static_cast<uint8_t>(s); + m_currentPresetSource[ch] = PresetSource::Rom; + found = true; + break; + } + } + } + + if(!found) + { + m_currentProgram[ch] = 0; + m_currentBank[ch] = virusLib::BankNumber::EditBuffer; + m_currentPresetSource[ch] = PresetSource::Unknown; + } } - - if(!found) + else { m_currentProgram[ch] = 0; m_currentBank[ch] = virusLib::BankNumber::EditBuffer; @@ -636,4 +658,20 @@ namespace Virus return createSingleDump(_modifyBank ? toMidiByte(_newBank) : data[pluginLib::MidiDataType::Bank], _modifyProgram ? _newProgram : data[pluginLib::MidiDataType::Program], parameterValues); } + + void Controller::selectPrevPreset(uint8_t _part) + { + if(getCurrentPartProgram(_part) > 0) + { + setCurrentPartPreset(_part, getCurrentPartBank(_part), getCurrentPartProgram(_part) - 1); + } + } + + void Controller::selectNextPreset(uint8_t _part) + { + if(getCurrentPartProgram(_part) < m_singles[0].size()) + { + setCurrentPartPreset(_part, getCurrentPartBank(_part), getCurrentPartProgram(_part) + 1); + } + } }; // namespace Virus diff --git a/source/jucePlugin/VirusController.h b/source/jucePlugin/VirusController.h @@ -15,8 +15,6 @@ namespace Virus class Controller : public pluginLib::Controller, juce::Timer { public: - static constexpr size_t kDataSizeInBytes = 256; // same for multi and single - struct SinglePatch { virusLib::BankNumber bankNumber = static_cast<virusLib::BankNumber>(0); @@ -46,6 +44,20 @@ namespace Virus Count }; + enum class PresetSource + { + Unknown, + Rom, + Browser + }; + + struct CurrentPreset + { + uint8_t program = 0; + virusLib::BankNumber bank = virusLib::BankNumber::EditBuffer; + PresetSource source = PresetSource::Unknown; + }; + Controller(AudioPluginAudioProcessor &, unsigned char deviceId = 0x00); ~Controller() override; @@ -56,6 +68,9 @@ namespace Virus std::vector<uint8_t> createSingleDump(uint8_t _bank, uint8_t _program, const pluginLib::MidiPacket::ParamValues& _paramValues); std::vector<uint8_t> modifySingleDump(const std::vector<uint8_t>& _sysex, virusLib::BankNumber _newBank, uint8_t _newProgram, bool _modifyBank, bool _modifyProgram); + void selectPrevPreset(uint8_t _part); + void selectNextPreset(uint8_t _part); + static void printMessage(const SysEx &); juce::Value* getParamValue(uint8_t ch, uint8_t bank, uint8_t paramIndex); @@ -72,10 +87,15 @@ namespace Virus void setSinglePresetName(uint8_t _part, const juce::String& _name); bool isMultiMode() const; - // part 0 - 15 (ignored when single! 0x40...) + + // part 0 - 15 (ignored when single! 0x40...) void setCurrentPartPreset(uint8_t _part, virusLib::BankNumber _bank, uint8_t _prg); - virusLib::BankNumber getCurrentPartBank(uint8_t _part) const; + void setCurrentPartPresetSource(uint8_t _part, PresetSource _source); + + virusLib::BankNumber getCurrentPartBank(uint8_t _part) const; uint8_t getCurrentPartProgram(uint8_t _part) const; + PresetSource getCurrentPartPresetSource(uint8_t _part) const; + juce::String getCurrentPartPresetName(uint8_t _part) const; uint32_t getBankCount() const { return static_cast<uint32_t>(m_singles.size()); } uint8_t getCurrentPart() const { return m_currentPart; } @@ -126,6 +146,7 @@ namespace Virus unsigned char m_deviceId; virusLib::BankNumber m_currentBank[16]{}; uint8_t m_currentProgram[16]{}; + PresetSource m_currentPresetSource[16]{PresetSource::Unknown}; uint8_t m_currentPart = 0; juce::PropertiesFile *m_config; }; diff --git a/source/jucePlugin/ui3/Parts.cpp b/source/jucePlugin/ui3/Parts.cpp @@ -75,14 +75,9 @@ namespace genericVirusUI if(m_presetPrev.size() == 1) _part = m_editor.getController().getCurrentPart(); - 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); - } + auto* pb = m_editor.getPatchBrowser(); + if(!pb || !pb->selectPrevPreset()) + m_editor.getController().selectPrevPreset(static_cast<uint8_t>(_part)); } void Parts::selectNextPreset(size_t _part) const @@ -90,13 +85,9 @@ namespace genericVirusUI if(m_presetNext.size() == 1) _part = m_editor.getController().getCurrentPart(); - 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); - } + auto* pb = m_editor.getPatchBrowser(); + if(!pb || !pb->selectNextPreset()) + m_editor.getController().selectNextPreset(static_cast<uint8_t>(_part)); } void Parts::selectPreset(size_t _part) const diff --git a/source/jucePlugin/ui3/PatchBrowser.cpp b/source/jucePlugin/ui3/PatchBrowser.cpp @@ -11,8 +11,6 @@ using namespace juce; -const juce::Array<juce::String> ModelList = {"A","B","C","TI"}; - namespace genericVirusUI { virusLib::VirusModel guessVersion(const uint8_t v) @@ -213,6 +211,16 @@ namespace genericVirusUI return 0; } + bool PatchBrowser::selectPrevPreset() + { + return selectPrevNextPreset(-1); + } + + bool PatchBrowser::selectNextPreset() + { + return selectPrevNextPreset(1); + } + void PatchBrowser::fileClicked(const File& file, const MouseEvent& e) { const auto ext = file.getFileExtension().toLowerCase(); @@ -310,6 +318,8 @@ namespace genericVirusUI m_controller.sendSysEx(msg); m_controller.requestSingle(0x0, program); + m_controller.setCurrentPartPresetSource(m_controller.getCurrentPart(), Virus::Controller::PresetSource::Browser); + m_properties->setValue("virus_selected_patch", patch.name); } @@ -449,6 +459,34 @@ namespace genericVirusUI m_patchList.selectRow(selectIndex); } + bool PatchBrowser::selectPrevNextPreset(int _dir) + { + const auto part = m_controller.getCurrentPart(); + + if(m_controller.getCurrentPartPresetSource(part) == Virus::Controller::PresetSource::Rom) + return false; + + if(m_filteredPatches.isEmpty()) + return false; + + const auto idx = m_patchList.getSelectedRow(); + if(idx < 0) + return false; + + const auto name = m_controller.getCurrentPartPresetName(part); + + if(m_filteredPatches[idx].name != name) + return false; + + const auto newIdx = idx + _dir; + + if(newIdx < 0 || newIdx >= m_filteredPatches.size()) + return false; + + m_patchList.selectRow(newIdx); + return true; + } + bool PatchBrowser::initializePatch(const Virus::Controller& _controller, Patch& _patch) { const auto& c = _controller; diff --git a/source/jucePlugin/ui3/PatchBrowser.h b/source/jucePlugin/ui3/PatchBrowser.h @@ -41,6 +41,9 @@ namespace genericVirusUI static bool load(const Virus::Controller& _controller, std::vector<Patch>& _result, std::set<std::string>* _dedupeChecksums, const std::vector<uint8_t>& _data); static uint32_t loadBankFile(const Virus::Controller& _controller, std::vector<Patch>& _result, std::set<std::string>* _dedupeChecksums, const juce::File& file); + bool selectPrevPreset(); + bool selectNextPreset(); + private: static bool initializePatch(const Virus::Controller& _controller, Patch& _patch); @@ -70,6 +73,8 @@ namespace genericVirusUI void fillPatchList(const std::vector<Patch>& _patches); void refreshPatchList(); + bool selectPrevNextPreset(int _dir); + class PatchBrowserSorter; enum Columns diff --git a/source/jucePlugin/ui3/VirusEditor.cpp b/source/jucePlugin/ui3/VirusEditor.cpp @@ -147,6 +147,11 @@ namespace genericVirusUI return nullptr; } + PatchBrowser* VirusEditor::getPatchBrowser() + { + return m_patchBrowser.get(); + } + const char* VirusEditor::getResourceByFilename(const std::string& _name, uint32_t& _dataSize) { if(!m_skinFolder.empty()) diff --git a/source/jucePlugin/ui3/VirusEditor.h b/source/jucePlugin/ui3/VirusEditor.h @@ -29,6 +29,8 @@ namespace genericVirusUI static const char* findNamedResourceByFilename(const std::string& _filename, uint32_t& _size); + PatchBrowser* getPatchBrowser(); + private: const char* getResourceByFilename(const std::string& _name, uint32_t& _dataSize) override; int getParameterIndexByName(const std::string& _name) override;