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 07ae6c409d65e1186447e59ce418187e79c23632
parent 2fccfd62984d6bb416458de95074de15d4ad9ef1
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date:   Fri,  9 Aug 2024 20:00:45 +0200

rework/cleanup namespaces

Diffstat:
Msource/jucePluginEditorLib/pluginEditorState.h | 2--
Msource/mqJucePlugin/PluginEditorState.cpp | 101+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msource/mqJucePlugin/PluginEditorState.h | 26++++++++++++++------------
Msource/mqJucePlugin/PluginProcessor.cpp | 66+++++++++++++++++++++++++++++++++---------------------------------
Msource/mqJucePlugin/PluginProcessor.h | 28+++++++++++++---------------
Msource/mqJucePlugin/mqController.cpp | 905++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msource/mqJucePlugin/mqController.h | 207++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msource/mqJucePlugin/mqEditor.h | 5++---
Msource/mqJucePlugin/mqFrontPanel.h | 3+--
Msource/mqJucePlugin/mqPartButton.cpp | 25++++++++++++++-----------
Msource/mqJucePlugin/mqPartButton.h | 23+++++++++++------------
Msource/mqJucePlugin/mqPartSelect.cpp | 103+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msource/mqJucePlugin/mqPartSelect.h | 44+++++++++++++++++++++-----------------------
Msource/mqJucePlugin/mqPatchManager.h | 3+--
Msource/nord/n2x/n2xJucePlugin/n2xController.h | 4++--
Msource/nord/n2x/n2xJucePlugin/n2xPluginEditorState.cpp | 93+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msource/nord/n2x/n2xJucePlugin/n2xPluginEditorState.h | 23+++++++++++++----------
Msource/nord/n2x/n2xJucePlugin/n2xPluginProcessor.cpp | 64+++++++++++++++++++++++++++++++++-------------------------------
Msource/nord/n2x/n2xJucePlugin/n2xPluginProcessor.h | 23+++++++++++++----------
Msource/osTIrusJucePlugin/OsTIrusEditorState.cpp | 2+-
Msource/osTIrusJucePlugin/OsTIrusEditorState.h | 6++----
Msource/osTIrusJucePlugin/OsTIrusProcessor.h | 2+-
Msource/osirusJucePlugin/OsirusEditorState.cpp | 2+-
Msource/osirusJucePlugin/OsirusEditorState.h | 6++----
Msource/osirusJucePlugin/OsirusProcessor.h | 2+-
Msource/virusJucePlugin/FxPage.cpp | 2+-
Msource/virusJucePlugin/Leds.cpp | 2+-
Msource/virusJucePlugin/Leds.h | 9++++++---
Msource/virusJucePlugin/ParameterNames.h | 2+-
Msource/virusJucePlugin/Parts.cpp | 8++++----
Msource/virusJucePlugin/PatchManager.cpp | 6+++---
Msource/virusJucePlugin/PatchManager.h | 4++--
Msource/virusJucePlugin/VirusController.cpp | 2+-
Msource/virusJucePlugin/VirusController.h | 8+++-----
Msource/virusJucePlugin/VirusEditor.cpp | 8++++----
Msource/virusJucePlugin/VirusEditor.h | 11+++++++----
Msource/virusJucePlugin/VirusEditorState.cpp | 176++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msource/virusJucePlugin/VirusEditorState.h | 22+++++++++++++---------
Msource/virusJucePlugin/VirusProcessor.cpp | 195++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msource/virusJucePlugin/VirusProcessor.h | 106++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msource/xtJucePlugin/PluginEditorState.cpp | 96+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msource/xtJucePlugin/PluginEditorState.h | 23+++++++++++++----------
Msource/xtJucePlugin/PluginProcessor.cpp | 60++++++++++++++++++++++++++++++------------------------------
Msource/xtJucePlugin/PluginProcessor.h | 27+++++++++++++--------------
Msource/xtJucePlugin/weData.h | 4++--
Msource/xtJucePlugin/xtController.cpp | 1072++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msource/xtJucePlugin/xtController.h | 237++++++++++++++++++++++++++++++++++++++++---------------------------------------
Msource/xtJucePlugin/xtEditor.h | 5++---
Msource/xtJucePlugin/xtLcd.cpp | 112+++++++++++++++++++++++++++++++++++++++++--------------------------------------
Msource/xtJucePlugin/xtLcd.h | 38+++++++++++++++++++++-----------------
Msource/xtJucePlugin/xtPatchManager.h | 3+--
51 files changed, 2026 insertions(+), 1980 deletions(-)

diff --git a/source/jucePluginEditorLib/pluginEditorState.h b/source/jucePluginEditorLib/pluginEditorState.h @@ -12,8 +12,6 @@ namespace juce class Component; } -class VirusProcessor; - namespace jucePluginEditorLib { class Editor; diff --git a/source/mqJucePlugin/PluginEditorState.cpp b/source/mqJucePlugin/PluginEditorState.cpp @@ -7,69 +7,71 @@ #include "synthLib/os.h" -const std::vector<PluginEditorState::Skin> g_includedSkins = +namespace mqJucePlugin { - {"Editor", "mqDefault.json", ""}, - {"Device", "mqFrontPanel.json", ""} -}; + const std::vector<PluginEditorState::Skin> g_includedSkins = + { + {"Editor", "mqDefault.json", ""}, + {"Device", "mqFrontPanel.json", ""} + }; -PluginEditorState::PluginEditorState(AudioPluginAudioProcessor& _processor) : jucePluginEditorLib::PluginEditorState(_processor, _processor.getController(), g_includedSkins) -{ - loadDefaultSkin(); -} + PluginEditorState::PluginEditorState(AudioPluginAudioProcessor& _processor) : jucePluginEditorLib::PluginEditorState(_processor, _processor.getController(), g_includedSkins) + { + loadDefaultSkin(); + } -void PluginEditorState::initContextMenu(juce::PopupMenu& _menu) -{ - jucePluginEditorLib::PluginEditorState::initContextMenu(_menu); + void PluginEditorState::initContextMenu(juce::PopupMenu& _menu) + { + jucePluginEditorLib::PluginEditorState::initContextMenu(_menu); - auto& p = m_processor; + auto& p = m_processor; - const auto gain = static_cast<int>(std::roundf(p.getOutputGain())); + const auto gain = static_cast<int>(std::roundf(p.getOutputGain())); - juce::PopupMenu gainMenu; + juce::PopupMenu gainMenu; - gainMenu.addItem("0 dB (default)", true, gain == 1, [&p] { p.setOutputGain(1); }); - gainMenu.addItem("+6 dB", true, gain == 2, [&p] { p.setOutputGain(2); }); - gainMenu.addItem("+12 dB", true, gain == 4, [&p] { p.setOutputGain(4); }); + gainMenu.addItem("0 dB (default)", true, gain == 1, [&p] { p.setOutputGain(1); }); + gainMenu.addItem("+6 dB", true, gain == 2, [&p] { p.setOutputGain(2); }); + gainMenu.addItem("+12 dB", true, gain == 4, [&p] { p.setOutputGain(4); }); - _menu.addSubMenu("Output Gain", gainMenu); + _menu.addSubMenu("Output Gain", gainMenu); - jucePluginEditorLib::MidiPorts::createMidiPortsMenu(_menu, p.getMidiPorts()); -} + jucePluginEditorLib::MidiPorts::createMidiPortsMenu(_menu, p.getMidiPorts()); + } -bool PluginEditorState::initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) -{ - jucePluginEditorLib::PluginEditorState::initAdvancedContextMenu(_menu, _enabled); - - const auto percent = m_processor.getDspClockPercent(); - const auto hz = m_processor.getDspClockHz(); + bool PluginEditorState::initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) + { + jucePluginEditorLib::PluginEditorState::initAdvancedContextMenu(_menu, _enabled); - juce::PopupMenu clockMenu; + const auto percent = m_processor.getDspClockPercent(); + const auto hz = m_processor.getDspClockHz(); - auto makeEntry = [&](const int _percent) - { - const auto mhz = hz * _percent / 100 / 1000000; - std::stringstream ss; - ss << _percent << "% (" << mhz << " MHz)"; - if(_percent == 100) - ss << " (Default)"; - clockMenu.addItem(ss.str(), _enabled, percent == _percent, [this, _percent] { m_processor.setDspClockPercent(_percent); }); - }; + juce::PopupMenu clockMenu; - makeEntry(50); - makeEntry(75); - makeEntry(100); - makeEntry(125); - makeEntry(150); - makeEntry(200); + auto makeEntry = [&](const int _percent) + { + const auto mhz = hz * _percent / 100 / 1000000; + std::stringstream ss; + ss << _percent << "% (" << mhz << " MHz)"; + if(_percent == 100) + ss << " (Default)"; + clockMenu.addItem(ss.str(), _enabled, percent == _percent, [this, _percent] { m_processor.setDspClockPercent(_percent); }); + }; - _menu.addSubMenu("DSP Clock", clockMenu); + makeEntry(50); + makeEntry(75); + makeEntry(100); + makeEntry(125); + makeEntry(150); + makeEntry(200); - return true; -} + _menu.addSubMenu("DSP Clock", clockMenu); + return true; + } -jucePluginEditorLib::Editor* PluginEditorState::createEditor(const Skin& _skin) -{ - return new mqJucePlugin::Editor(m_processor, m_parameterBinding, _skin.folder, _skin.jsonFilename); -} + jucePluginEditorLib::Editor* PluginEditorState::createEditor(const Skin& _skin) + { + return new mqJucePlugin::Editor(m_processor, m_parameterBinding, _skin.folder, _skin.jsonFilename); + } +} +\ No newline at end of file diff --git a/source/mqJucePlugin/PluginEditorState.h b/source/mqJucePlugin/PluginEditorState.h @@ -1,7 +1,5 @@ #pragma once -#include <functional> - #include "jucePluginEditorLib/pluginEditorState.h" namespace juce @@ -9,14 +7,17 @@ namespace juce class Component; } -class AudioPluginAudioProcessor; - -class PluginEditorState : public jucePluginEditorLib::PluginEditorState +namespace mqJucePlugin { -public: - explicit PluginEditorState(AudioPluginAudioProcessor& _processor); - void initContextMenu(juce::PopupMenu& _menu) override; - bool initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) override; -private: - jucePluginEditorLib::Editor* createEditor(const Skin& _skin) override; -}; + class AudioPluginAudioProcessor; + + class PluginEditorState : public jucePluginEditorLib::PluginEditorState + { + public: + explicit PluginEditorState(AudioPluginAudioProcessor& _processor); + void initContextMenu(juce::PopupMenu& _menu) override; + bool initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) override; + private: + jucePluginEditorLib::Editor* createEditor(const Skin& _skin) override; + }; +} +\ No newline at end of file diff --git a/source/mqJucePlugin/PluginProcessor.cpp b/source/mqJucePlugin/PluginProcessor.cpp @@ -6,8 +6,6 @@ #include "jucePluginLib/processor.h" #include "mqLib/device.h" -class Controller; - namespace { juce::PropertiesFile::Options getOptions() @@ -21,44 +19,46 @@ namespace } } -//============================================================================== -AudioPluginAudioProcessor::AudioPluginAudioProcessor() : - Processor(BusesProperties() - .withInput("Input", juce::AudioChannelSet::stereo(), true) - .withOutput("Output", juce::AudioChannelSet::stereo(), true) +namespace mqJucePlugin +{ + class Controller; + + AudioPluginAudioProcessor::AudioPluginAudioProcessor() : + Processor(BusesProperties() + .withInput("Input", juce::AudioChannelSet::stereo(), true) + .withOutput("Output", juce::AudioChannelSet::stereo(), true) #if JucePlugin_IsSynth - .withOutput("Out 2", juce::AudioChannelSet::stereo(), true) - .withOutput("Out 3", juce::AudioChannelSet::stereo(), true) + .withOutput("Out 2", juce::AudioChannelSet::stereo(), true) + .withOutput("Out 3", juce::AudioChannelSet::stereo(), true) #endif - , getOptions(), pluginLib::Processor::Properties{JucePlugin_Name, JucePlugin_IsSynth, JucePlugin_WantsMidiInput, JucePlugin_ProducesMidiOutput, JucePlugin_IsMidiEffect}) -{ - getController(); - const auto latencyBlocks = getConfig().getIntValue("latencyBlocks", static_cast<int>(getPlugin().getLatencyBlocks())); - Processor::setLatencyBlocks(latencyBlocks); -} + , getOptions(), pluginLib::Processor::Properties{JucePlugin_Name, JucePlugin_IsSynth, JucePlugin_WantsMidiInput, JucePlugin_ProducesMidiOutput, JucePlugin_IsMidiEffect}) + { + getController(); + const auto latencyBlocks = getConfig().getIntValue("latencyBlocks", static_cast<int>(getPlugin().getLatencyBlocks())); + Processor::setLatencyBlocks(latencyBlocks); + } -AudioPluginAudioProcessor::~AudioPluginAudioProcessor() -{ - destroyEditorState(); -} + AudioPluginAudioProcessor::~AudioPluginAudioProcessor() + { + destroyEditorState(); + } -jucePluginEditorLib::PluginEditorState* AudioPluginAudioProcessor::createEditorState() -{ - return new PluginEditorState(*this); -} -synthLib::Device* AudioPluginAudioProcessor::createDevice() -{ - return new mqLib::Device(); -} + jucePluginEditorLib::PluginEditorState* AudioPluginAudioProcessor::createEditorState() + { + return new PluginEditorState(*this); + } + synthLib::Device* AudioPluginAudioProcessor::createDevice() + { + return new mqLib::Device(); + } -pluginLib::Controller* AudioPluginAudioProcessor::createController() -{ - return new Controller(*this); + pluginLib::Controller* AudioPluginAudioProcessor::createController() + { + return new Controller(*this); + } } -//============================================================================== -// This creates new instances of the plugin.. juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() { - return new AudioPluginAudioProcessor(); + return new mqJucePlugin::AudioPluginAudioProcessor(); } diff --git a/source/mqJucePlugin/PluginProcessor.h b/source/mqJucePlugin/PluginProcessor.h @@ -2,22 +2,20 @@ #include "jucePluginEditorLib/pluginProcessor.h" -//============================================================================== -class AudioPluginAudioProcessor : public jucePluginEditorLib::Processor +namespace mqJucePlugin { -public: - AudioPluginAudioProcessor(); - ~AudioPluginAudioProcessor() override; + class AudioPluginAudioProcessor : public jucePluginEditorLib::Processor + { + public: + AudioPluginAudioProcessor(); + ~AudioPluginAudioProcessor() override; - jucePluginEditorLib::PluginEditorState* createEditorState() override; + jucePluginEditorLib::PluginEditorState* createEditorState() override; - // _____________ - // - synthLib::Device* createDevice() override; + synthLib::Device* createDevice() override; - pluginLib::Controller* createController() override; -private: - - //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AudioPluginAudioProcessor) -}; + pluginLib::Controller* createController() override; + private: + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AudioPluginAudioProcessor) + }; +} diff --git a/source/mqJucePlugin/mqController.cpp b/source/mqJucePlugin/mqController.cpp @@ -12,555 +12,558 @@ #include "dsp56kEmu/logging.h" -constexpr const char* g_midiPacketNames[] = +namespace mqJucePlugin { - "requestsingle", - "requestmulti", - "requestdrum", - "requestsinglebank", - "requestmultibank", - "requestdrumbank", - "requestglobal", - "requestallsingles", - "singleparameterchange", - "multiparameterchange", - "globalparameterchange", - "singledump", - "singledump_Q", - "multidump", - "globaldump", - "emuRequestLcd", - "emuRequestLeds", - "emuSendButton", - "emuSendRotary" -}; - -static_assert(std::size(g_midiPacketNames) == static_cast<size_t>(Controller::MidiPacketType::Count)); - -static const char* midiPacketName(Controller::MidiPacketType _type) -{ - return g_midiPacketNames[static_cast<uint32_t>(_type)]; -} + constexpr const char* g_midiPacketNames[] = + { + "requestsingle", + "requestmulti", + "requestdrum", + "requestsinglebank", + "requestmultibank", + "requestdrumbank", + "requestglobal", + "requestallsingles", + "singleparameterchange", + "multiparameterchange", + "globalparameterchange", + "singledump", + "singledump_Q", + "multidump", + "globaldump", + "emuRequestLcd", + "emuRequestLeds", + "emuSendButton", + "emuSendRotary" + }; + + static_assert(std::size(g_midiPacketNames) == static_cast<size_t>(Controller::MidiPacketType::Count)); + + static const char* midiPacketName(Controller::MidiPacketType _type) + { + return g_midiPacketNames[static_cast<uint32_t>(_type)]; + } -Controller::Controller(AudioPluginAudioProcessor& p, unsigned char _deviceId) : pluginLib::Controller(p, loadParameterDescriptions()), m_deviceId(_deviceId) -{ - registerParams(p); + Controller::Controller(AudioPluginAudioProcessor& p, unsigned char _deviceId) : pluginLib::Controller(p, loadParameterDescriptions()), m_deviceId(_deviceId) + { + registerParams(p); -// sendSysEx(RequestAllSingles); - sendSysEx(RequestGlobal); -// sendGlobalParameterChange(mqLib::GlobalParameter::SingleMultiMode, 1); + // sendSysEx(RequestAllSingles); + sendSysEx(RequestGlobal); + // sendGlobalParameterChange(mqLib::GlobalParameter::SingleMultiMode, 1); - onPlayModeChanged.addListener(0, [this](bool multiMode) + onPlayModeChanged.addListener(0, [this](bool multiMode) + { + requestAllPatches(); + }); + } + + Controller::~Controller() = default; + + void Controller::setFrontPanel(mqJucePlugin::FrontPanel* _frontPanel) { - requestAllPatches(); - }); -} + m_frontPanel = _frontPanel; + } -Controller::~Controller() = default; + void Controller::sendSingle(const std::vector<uint8_t>& _sysex) + { + sendSingle(_sysex, getCurrentPart()); + } -void Controller::setFrontPanel(mqJucePlugin::FrontPanel* _frontPanel) -{ - m_frontPanel = _frontPanel; -} + void Controller::sendSingle(const std::vector<uint8_t>& _sysex, const uint8_t _part) + { + auto data = _sysex; -void Controller::sendSingle(const std::vector<uint8_t>& _sysex) -{ - sendSingle(_sysex, getCurrentPart()); -} + data[wLib::IdxBuffer] = static_cast<uint8_t>(isMultiMode() ? mqLib::MidiBufferNum::SingleEditBufferMultiMode : mqLib::MidiBufferNum::SingleEditBufferSingleMode); + data[wLib::IdxLocation] = isMultiMode() ? _part : 0; + data[wLib::IdxDeviceId] = m_deviceId; -void Controller::sendSingle(const std::vector<uint8_t>& _sysex, const uint8_t _part) -{ - auto data = _sysex; + const auto* p = getMidiPacket(g_midiPacketNames[SingleDump]); + + if (!p->updateChecksums(data)) + { + p = getMidiPacket(g_midiPacketNames[SingleDumpQ]); + + if(!p->updateChecksums(data)) + return; + } - data[wLib::IdxBuffer] = static_cast<uint8_t>(isMultiMode() ? mqLib::MidiBufferNum::SingleEditBufferMultiMode : mqLib::MidiBufferNum::SingleEditBufferSingleMode); - data[wLib::IdxLocation] = isMultiMode() ? _part : 0; - data[wLib::IdxDeviceId] = m_deviceId; + pluginLib::Controller::sendSysEx(data); - const auto* p = getMidiPacket(g_midiPacketNames[SingleDump]); + sendLockedParameters(_part); - if (!p->updateChecksums(data)) + requestSingle(isMultiMode() ? mqLib::MidiBufferNum::SingleEditBufferMultiMode : mqLib::MidiBufferNum::SingleEditBufferSingleMode, + isMultiMode() ? mqLib::MidiSoundLocation::EditBufferFirstMultiSingle : mqLib::MidiSoundLocation::EditBufferCurrentSingle); + } + + std::string Controller::loadParameterDescriptions() { - p = getMidiPacket(g_midiPacketNames[SingleDumpQ]); + const auto name = "parameterDescriptions_mq.json"; + const auto path = synthLib::getModulePath() + name; - if(!p->updateChecksums(data)) - return; + const std::ifstream f(path.c_str(), std::ios::in); + if(f.is_open()) + { + std::stringstream buf; + buf << f.rdbuf(); + return buf.str(); + } + + uint32_t size; + const auto res = mqJucePlugin::Editor::findEmbeddedResource(name, size); + if(res) + return {res, size}; + return {}; } - pluginLib::Controller::sendSysEx(data); + void Controller::onStateLoaded() + { + } - sendLockedParameters(_part); + std::string Controller::getSingleName(const pluginLib::MidiPacket::ParamValues& _values) const + { + std::string name; + for(uint32_t i=0; i<16; ++i) + { + char paramName[16]; + sprintf(paramName, "Name%02u", i); + const auto idx = getParameterIndexByName(paramName); + if(idx == InvalidParameterIndex) + break; - requestSingle(isMultiMode() ? mqLib::MidiBufferNum::SingleEditBufferMultiMode : mqLib::MidiBufferNum::SingleEditBufferSingleMode, - isMultiMode() ? mqLib::MidiSoundLocation::EditBufferFirstMultiSingle : mqLib::MidiSoundLocation::EditBufferCurrentSingle); -} + const auto it = _values.find(std::make_pair(pluginLib::MidiPacket::AnyPart, idx)); + if(it == _values.end()) + break; -std::string Controller::loadParameterDescriptions() -{ - const auto name = "parameterDescriptions_mq.json"; - const auto path = synthLib::getModulePath() + name; - - const std::ifstream f(path.c_str(), std::ios::in); - if(f.is_open()) - { - std::stringstream buf; - buf << f.rdbuf(); - return buf.str(); - } - - uint32_t size; - const auto res = mqJucePlugin::Editor::findEmbeddedResource(name, size); - if(res) - return {res, size}; - return {}; -} + name += static_cast<char>(it->second); + } + return name; + } -void Controller::onStateLoaded() -{ -} + std::string Controller::getSingleName(const pluginLib::MidiPacket::AnyPartParamValues& _values) const + { + return getString(_values, "Name", 16); + } -std::string Controller::getSingleName(const pluginLib::MidiPacket::ParamValues& _values) const -{ - std::string name; - for(uint32_t i=0; i<16; ++i) - { - char paramName[16]; - sprintf(paramName, "Name%02u", i); - const auto idx = getParameterIndexByName(paramName); - if(idx == InvalidParameterIndex) - break; - - const auto it = _values.find(std::make_pair(pluginLib::MidiPacket::AnyPart, idx)); - if(it == _values.end()) - break; - - name += static_cast<char>(it->second); - } - return name; -} + std::string Controller::getCategory(const pluginLib::MidiPacket::AnyPartParamValues& _values) const + { + return getString(_values, "Category", 4); + } -std::string Controller::getSingleName(const pluginLib::MidiPacket::AnyPartParamValues& _values) const -{ - return getString(_values, "Name", 16); -} + std::string Controller::getString(const pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, const size_t _len) const + { + std::string name; + for(uint32_t i=0; i<_len; ++i) + { + char paramName[64]; + snprintf(paramName, sizeof(paramName), "%s%02u", _prefix.c_str(), i); -std::string Controller::getCategory(const pluginLib::MidiPacket::AnyPartParamValues& _values) const -{ - return getString(_values, "Category", 4); -} + const auto idx = getParameterIndexByName(paramName); + if(idx == InvalidParameterIndex) + break; -std::string Controller::getString(const pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, const size_t _len) const -{ - std::string name; - for(uint32_t i=0; i<_len; ++i) - { - char paramName[64]; - snprintf(paramName, sizeof(paramName), "%s%02u", _prefix.c_str(), i); - - const auto idx = getParameterIndexByName(paramName); - if(idx == InvalidParameterIndex) - break; - - const auto it = _values[idx]; - if(!it) - break; - - name += static_cast<char>(*it); - } - return name; -} + const auto it = _values[idx]; + if(!it) + break; -bool Controller::setSingleName(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const -{ - return setString(_values, "Name", 16, _value); -} + name += static_cast<char>(*it); + } + return name; + } -bool Controller::setCategory(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const -{ - return setString(_values, "Category", 4, _value); -} + bool Controller::setSingleName(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const + { + return setString(_values, "Name", 16, _value); + } -void Controller::parseSingle(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params) -{ - Patch patch; - patch.data = _msg; - patch.name = getSingleName(_params); + bool Controller::setCategory(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const + { + return setString(_values, "Category", 4, _value); + } - const auto bank = _data.at(pluginLib::MidiDataType::Bank); - const auto prog = _data.at(pluginLib::MidiDataType::Program); + void Controller::parseSingle(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params) + { + Patch patch; + patch.data = _msg; + patch.name = getSingleName(_params); - if(bank == static_cast<uint8_t>(mqLib::MidiBufferNum::SingleEditBufferSingleMode) && prog == static_cast<uint8_t>(mqLib::MidiSoundLocation::EditBufferCurrentSingle)) - { - m_singleEditBuffer = patch; + const auto bank = _data.at(pluginLib::MidiDataType::Bank); + const auto prog = _data.at(pluginLib::MidiDataType::Program); - if(!isMultiMode()) - applyPatchParameters(_params, 0); - } - else if(bank == static_cast<uint8_t>(mqLib::MidiBufferNum::SingleEditBufferMultiMode)) - { - m_singleEditBuffers[prog] = patch; - - if (isMultiMode()) - applyPatchParameters(_params, prog); - - // if we switched to multi, all singles have to be requested. However, we cannot send all requests at once (device will miss some) - // so we chain them one after the other - if(prog + 1 < m_singleEditBuffers.size()) - requestSingle(mqLib::MidiBufferNum::SingleEditBufferMultiMode, mqLib::MidiSoundLocation::EditBufferFirstMultiSingle, prog + 1); - } -} + if(bank == static_cast<uint8_t>(mqLib::MidiBufferNum::SingleEditBufferSingleMode) && prog == static_cast<uint8_t>(mqLib::MidiSoundLocation::EditBufferCurrentSingle)) + { + m_singleEditBuffer = patch; -void Controller::parseMulti(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params) -{ - Patch patch; - patch.data = _msg; - patch.name = getSingleName(_params); + if(!isMultiMode()) + applyPatchParameters(_params, 0); + } + else if(bank == static_cast<uint8_t>(mqLib::MidiBufferNum::SingleEditBufferMultiMode)) + { + m_singleEditBuffers[prog] = patch; + + if (isMultiMode()) + applyPatchParameters(_params, prog); - const auto bank = _data.at(pluginLib::MidiDataType::Bank); -// const auto prog = _data.at(pluginLib::MidiDataType::Program); + // if we switched to multi, all singles have to be requested. However, we cannot send all requests at once (device will miss some) + // so we chain them one after the other + if(prog + 1 < m_singleEditBuffers.size()) + requestSingle(mqLib::MidiBufferNum::SingleEditBufferMultiMode, mqLib::MidiSoundLocation::EditBufferFirstMultiSingle, prog + 1); + } + } - if(bank == static_cast<uint8_t>(mqLib::MidiBufferNum::MultiEditBuffer)) + void Controller::parseMulti(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params) { - applyPatchParameters(_params, 0); + Patch patch; + patch.data = _msg; + patch.name = getSingleName(_params); + + const auto bank = _data.at(pluginLib::MidiDataType::Bank); + // const auto prog = _data.at(pluginLib::MidiDataType::Program); + + if(bank == static_cast<uint8_t>(mqLib::MidiBufferNum::MultiEditBuffer)) + { + applyPatchParameters(_params, 0); + } } -} -bool Controller::parseSysexMessage(const pluginLib::SysEx& _msg, synthLib::MidiEventSource _source) -{ - if(_msg.size() >= 5) - { - const auto cmd = static_cast<mqLib::SysexCommand>(_msg[4]); - switch (cmd) - { - case mqLib::SysexCommand::EmuRotaries: - case mqLib::SysexCommand::EmuButtons: - case mqLib::SysexCommand::EmuLCD: - case mqLib::SysexCommand::EmuLCDCGRata: - case mqLib::SysexCommand::EmuLEDs: - if(m_frontPanel) - m_frontPanel->processSysex(_msg); - return true; - default: - break; - } - } - - LOG("Got sysex of size " << _msg.size()); - - std::string name; - pluginLib::MidiPacket::Data data; - pluginLib::MidiPacket::ParamValues parameterValues; - - if(!pluginLib::Controller::parseMidiPacket(name, data, parameterValues, _msg)) - return false; - - if(name == midiPacketName(SingleDump)) - { - parseSingle(_msg, data, parameterValues); - } - else if (name == midiPacketName(MultiDump)) - { - parseMulti(_msg, data, parameterValues); - } - else if(name == midiPacketName(GlobalDump)) - { - const auto lastPlayMode = isMultiMode(); - memcpy(m_globalData.data(), &_msg[5], sizeof(m_globalData)); - const auto newPlayMode = isMultiMode(); - - if(lastPlayMode != newPlayMode) - onPlayModeChanged(newPlayMode); - else - requestAllPatches(); - } - else if(name == midiPacketName(SingleParameterChange)) - { - const auto page = data[pluginLib::MidiDataType::Page]; - const auto index = data[pluginLib::MidiDataType::ParameterIndex]; - const auto part = data[pluginLib::MidiDataType::Part]; - const auto value = data[pluginLib::MidiDataType::ParameterValue]; - - auto& params = findSynthParam(part, page, index); - - for (auto& param : params) - param->setValueFromSynth(value, pluginLib::Parameter::Origin::Midi); - - LOG("Single parameter " << static_cast<int>(index) << ", page " << static_cast<int>(page) << " for part " << static_cast<int>(part) << " changed to value " << static_cast<int>(value)); - } - else if(name == midiPacketName(GlobalParameterChange)) - { - const auto index = (static_cast<uint32_t>(data[pluginLib::MidiDataType::Page]) << 7) + static_cast<uint32_t>(data[pluginLib::MidiDataType::ParameterIndex]); - const auto value = data[pluginLib::MidiDataType::ParameterValue]; - - if(m_globalData[index] != value) + bool Controller::parseSysexMessage(const pluginLib::SysEx& _msg, synthLib::MidiEventSource _source) + { + if(_msg.size() >= 5) { - LOG("Global parameter " << index << " changed to value " << static_cast<int>(value)); - m_globalData[index] = value; + const auto cmd = static_cast<mqLib::SysexCommand>(_msg[4]); + switch (cmd) + { + case mqLib::SysexCommand::EmuRotaries: + case mqLib::SysexCommand::EmuButtons: + case mqLib::SysexCommand::EmuLCD: + case mqLib::SysexCommand::EmuLCDCGRata: + case mqLib::SysexCommand::EmuLEDs: + if(m_frontPanel) + m_frontPanel->processSysex(_msg); + return true; + default: + break; + } + } - if (index == static_cast<uint32_t>(mqLib::GlobalParameter::SingleMultiMode)) + LOG("Got sysex of size " << _msg.size()); + + std::string name; + pluginLib::MidiPacket::Data data; + pluginLib::MidiPacket::ParamValues parameterValues; + + if(!pluginLib::Controller::parseMidiPacket(name, data, parameterValues, _msg)) + return false; + + if(name == midiPacketName(SingleDump)) + { + parseSingle(_msg, data, parameterValues); + } + else if (name == midiPacketName(MultiDump)) + { + parseMulti(_msg, data, parameterValues); + } + else if(name == midiPacketName(GlobalDump)) + { + const auto lastPlayMode = isMultiMode(); + memcpy(m_globalData.data(), &_msg[5], sizeof(m_globalData)); + const auto newPlayMode = isMultiMode(); + + if(lastPlayMode != newPlayMode) + onPlayModeChanged(newPlayMode); + else requestAllPatches(); } - } - else - { - LOG("Received unknown sysex of size " << _msg.size()); - return false; - } - return true; -} + else if(name == midiPacketName(SingleParameterChange)) + { + const auto page = data[pluginLib::MidiDataType::Page]; + const auto index = data[pluginLib::MidiDataType::ParameterIndex]; + const auto part = data[pluginLib::MidiDataType::Part]; + const auto value = data[pluginLib::MidiDataType::ParameterValue]; -bool Controller::parseControllerMessage(const synthLib::SMidiEvent&) -{ - // TODO - return false; -} + auto& params = findSynthParam(part, page, index); -bool Controller::parseMidiPacket(MidiPacketType _type, pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _params, const pluginLib::SysEx& _sysex) const -{ - const auto* p = getMidiPacket(g_midiPacketNames[_type]); - assert(p && "midi packet not found"); - return pluginLib::Controller::parseMidiPacket(*p, _data, _params, _sysex); -} + for (auto& param : params) + param->setValueFromSynth(value, pluginLib::Parameter::Origin::Midi); -bool Controller::sendSysEx(MidiPacketType _type) const -{ - std::map<pluginLib::MidiDataType, uint8_t> params; - return sendSysEx(_type, params); -} + LOG("Single parameter " << static_cast<int>(index) << ", page " << static_cast<int>(page) << " for part " << static_cast<int>(part) << " changed to value " << static_cast<int>(value)); + } + else if(name == midiPacketName(GlobalParameterChange)) + { + const auto index = (static_cast<uint32_t>(data[pluginLib::MidiDataType::Page]) << 7) + static_cast<uint32_t>(data[pluginLib::MidiDataType::ParameterIndex]); + const auto value = data[pluginLib::MidiDataType::ParameterValue]; -bool Controller::sendSysEx(const MidiPacketType _type, std::map<pluginLib::MidiDataType, uint8_t>& _params) const -{ - _params.insert(std::make_pair(pluginLib::MidiDataType::DeviceId, m_deviceId)); - return pluginLib::Controller::sendSysEx(midiPacketName(_type), _params); -} + if(m_globalData[index] != value) + { + LOG("Global parameter " << index << " changed to value " << static_cast<int>(value)); + m_globalData[index] = value; -bool Controller::isMultiMode() const -{ - return m_globalData[static_cast<uint32_t>(mqLib::GlobalParameter::SingleMultiMode)] != 0; -} + if (index == static_cast<uint32_t>(mqLib::GlobalParameter::SingleMultiMode)) + requestAllPatches(); + } + } + else + { + LOG("Received unknown sysex of size " << _msg.size()); + return false; + } + return true; + } -void Controller::setPlayMode(const bool _multiMode) -{ - const uint8_t playMode = _multiMode ? 1 : 0; + bool Controller::parseControllerMessage(const synthLib::SMidiEvent&) + { + // TODO + return false; + } - if(m_globalData[static_cast<uint32_t>(mqLib::GlobalParameter::SingleMultiMode)] == playMode) - return; + bool Controller::parseMidiPacket(MidiPacketType _type, pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _params, const pluginLib::SysEx& _sysex) const + { + const auto* p = getMidiPacket(g_midiPacketNames[_type]); + assert(p && "midi packet not found"); + return pluginLib::Controller::parseMidiPacket(*p, _data, _params, _sysex); + } - sendGlobalParameterChange(mqLib::GlobalParameter::SingleMultiMode, playMode); + bool Controller::sendSysEx(MidiPacketType _type) const + { + std::map<pluginLib::MidiDataType, uint8_t> params; + return sendSysEx(_type, params); + } - onPlayModeChanged(_multiMode); -} + bool Controller::sendSysEx(const MidiPacketType _type, std::map<pluginLib::MidiDataType, uint8_t>& _params) const + { + _params.insert(std::make_pair(pluginLib::MidiDataType::DeviceId, m_deviceId)); + return pluginLib::Controller::sendSysEx(midiPacketName(_type), _params); + } -void Controller::selectNextPreset() -{ - selectPreset(+1); -} + bool Controller::isMultiMode() const + { + return m_globalData[static_cast<uint32_t>(mqLib::GlobalParameter::SingleMultiMode)] != 0; + } -void Controller::selectPrevPreset() -{ - selectPreset(-1); -} + void Controller::setPlayMode(const bool _multiMode) + { + const uint8_t playMode = _multiMode ? 1 : 0; -std::vector<uint8_t> Controller::createSingleDump(const mqLib::MidiBufferNum _buffer, const mqLib::MidiSoundLocation _location, const uint8_t _locationOffset, const uint8_t _part) const -{ - pluginLib::MidiPacket::Data data; + if(m_globalData[static_cast<uint32_t>(mqLib::GlobalParameter::SingleMultiMode)] == playMode) + return; - data.insert(std::make_pair(pluginLib::MidiDataType::DeviceId, m_deviceId)); - data.insert(std::make_pair(pluginLib::MidiDataType::Bank, static_cast<uint8_t>(_buffer))); - data.insert(std::make_pair(pluginLib::MidiDataType::Program, static_cast<uint8_t>(_location) + _locationOffset)); + sendGlobalParameterChange(mqLib::GlobalParameter::SingleMultiMode, playMode); - std::vector<uint8_t> dst; + onPlayModeChanged(_multiMode); + } - if (!createMidiDataFromPacket(dst, midiPacketName(SingleDump), data, _part)) - return {}; + void Controller::selectNextPreset() + { + selectPreset(+1); + } - return dst; -} + void Controller::selectPrevPreset() + { + selectPreset(-1); + } -std::vector<uint8_t> Controller::createSingleDump(mqLib::MidiBufferNum _buffer, mqLib::MidiSoundLocation _location, const uint8_t _locationOffset, const pluginLib::MidiPacket::AnyPartParamValues& _values) const -{ - pluginLib::MidiPacket::Data data; + std::vector<uint8_t> Controller::createSingleDump(const mqLib::MidiBufferNum _buffer, const mqLib::MidiSoundLocation _location, const uint8_t _locationOffset, const uint8_t _part) const + { + pluginLib::MidiPacket::Data data; - data.insert(std::make_pair(pluginLib::MidiDataType::DeviceId, m_deviceId)); - data.insert(std::make_pair(pluginLib::MidiDataType::Bank, static_cast<uint8_t>(_buffer))); - data.insert(std::make_pair(pluginLib::MidiDataType::Program, static_cast<uint8_t>(_location) + _locationOffset)); + data.insert(std::make_pair(pluginLib::MidiDataType::DeviceId, m_deviceId)); + data.insert(std::make_pair(pluginLib::MidiDataType::Bank, static_cast<uint8_t>(_buffer))); + data.insert(std::make_pair(pluginLib::MidiDataType::Program, static_cast<uint8_t>(_location) + _locationOffset)); - std::vector<uint8_t> dst; + std::vector<uint8_t> dst; - if (!createMidiDataFromPacket(dst, midiPacketName(SingleDump), data, _values)) - return {}; + if (!createMidiDataFromPacket(dst, midiPacketName(SingleDump), data, _part)) + return {}; - return dst; -} + return dst; + } -bool Controller::parseSingle(pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _paramValues, const std::vector<uint8_t>& _sysex) const -{ - if(parseMidiPacket(SingleDump, _data, _paramValues, _sysex)) - return true; - return parseMidiPacket(SingleDumpQ, _data, _paramValues, _sysex); -} + std::vector<uint8_t> Controller::createSingleDump(mqLib::MidiBufferNum _buffer, mqLib::MidiSoundLocation _location, const uint8_t _locationOffset, const pluginLib::MidiPacket::AnyPartParamValues& _values) const + { + pluginLib::MidiPacket::Data data; -bool Controller::setString(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, size_t _len, const std::string& _value) const -{ - for(uint32_t i=0; i<_len && i <_value.size(); ++i) - { - char paramName[64]; - snprintf(paramName, sizeof(paramName), "%s%02u", _prefix.c_str(), i); - - const auto idx = getParameterIndexByName(paramName); - if(idx == InvalidParameterIndex) - break; - - _values[idx] = static_cast<uint8_t>(_value[i]); - } - return true; -} + data.insert(std::make_pair(pluginLib::MidiDataType::DeviceId, m_deviceId)); + data.insert(std::make_pair(pluginLib::MidiDataType::Bank, static_cast<uint8_t>(_buffer))); + data.insert(std::make_pair(pluginLib::MidiDataType::Program, static_cast<uint8_t>(_location) + _locationOffset)); -void Controller::selectPreset(int _offset) -{ - auto& current = isMultiMode() ? m_currentSingles[getCurrentPart()] : m_currentSingle; - - int index = static_cast<int>(current) + _offset; - - if (index < 0) - index += 300; - - if (index >= 300) - index -= 300; - - current = static_cast<uint32_t>(index); - - const int single = index % 100; - const int bank = index / 100; - - if (isMultiMode()) - { - // TODO: modify multi - } - else - { - sendMidiEvent(synthLib::M_CONTROLCHANGE, synthLib::MC_BANKSELECTMSB, m_deviceId); - sendMidiEvent(synthLib::M_CONTROLCHANGE, synthLib::MC_BANKSELECTLSB, static_cast<uint8_t>(mqLib::MidiBufferNum::SingleBankA) + bank); - sendMidiEvent(synthLib::M_PROGRAMCHANGE, static_cast<uint8_t>(single), 0); -/* - sendGlobalParameterChange(mqLib::GlobalParameter::InstrumentABankNumber, static_cast<uint8_t>(bank)); - sendGlobalParameterChange(mqLib::GlobalParameter::InstrumentASingleNumber, static_cast<uint8_t>(single)); -*/ } -} + std::vector<uint8_t> dst; -void Controller::sendParameterChange(const pluginLib::Parameter& _parameter, const pluginLib::ParamValue _value) -{ - const auto &desc = _parameter.getDescription(); + if (!createMidiDataFromPacket(dst, midiPacketName(SingleDump), data, _values)) + return {}; - std::map<pluginLib::MidiDataType, uint8_t> data; + return dst; + } - if (desc.page >= 100) + bool Controller::parseSingle(pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _paramValues, const std::vector<uint8_t>& _sysex) const { - uint8_t v; + if(parseMidiPacket(SingleDump, _data, _paramValues, _sysex)) + return true; + return parseMidiPacket(SingleDumpQ, _data, _paramValues, _sysex); + } - if (!combineParameterChange(v, g_midiPacketNames[MultiDump], _parameter, _value)) - return; + bool Controller::setString(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, size_t _len, const std::string& _value) const + { + for(uint32_t i=0; i<_len && i <_value.size(); ++i) + { + char paramName[64]; + snprintf(paramName, sizeof(paramName), "%s%02u", _prefix.c_str(), i); - const auto& dump = mqLib::State::Dumps[static_cast<int>(mqLib::State::DumpType::Multi)]; + const auto idx = getParameterIndexByName(paramName); + if(idx == InvalidParameterIndex) + break; - uint32_t idx = desc.index; + _values[idx] = static_cast<uint8_t>(_value[i]); + } + return true; + } - if(desc.page > 100) - idx += (static_cast<uint32_t>(mqLib::MultiParameter::Inst1) - static_cast<uint32_t>(mqLib::MultiParameter::Inst0)) * (desc.page - 101); + void Controller::selectPreset(int _offset) + { + auto& current = isMultiMode() ? m_currentSingles[getCurrentPart()] : m_currentSingle; - data.insert(std::make_pair(pluginLib::MidiDataType::Part, _parameter.getPart())); - data.insert(std::make_pair(pluginLib::MidiDataType::Page, idx >> 7)); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, idx & 0x7f)); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, v)); + int index = static_cast<int>(current) + _offset; + + if (index < 0) + index += 300; + + if (index >= 300) + index -= 300; + + current = static_cast<uint32_t>(index); + + const int single = index % 100; + const int bank = index / 100; - sendSysEx(MultiParameterChange, data); - return; + if (isMultiMode()) + { + // TODO: modify multi + } + else + { + sendMidiEvent(synthLib::M_CONTROLCHANGE, synthLib::MC_BANKSELECTMSB, m_deviceId); + sendMidiEvent(synthLib::M_CONTROLCHANGE, synthLib::MC_BANKSELECTLSB, static_cast<uint8_t>(mqLib::MidiBufferNum::SingleBankA) + bank); + sendMidiEvent(synthLib::M_PROGRAMCHANGE, static_cast<uint8_t>(single), 0); + /* + sendGlobalParameterChange(mqLib::GlobalParameter::InstrumentABankNumber, static_cast<uint8_t>(bank)); + sendGlobalParameterChange(mqLib::GlobalParameter::InstrumentASingleNumber, static_cast<uint8_t>(single)); + */ } } - uint8_t v; - if (!combineParameterChange(v, g_midiPacketNames[SingleDump], _parameter, _value)) - return; + void Controller::sendParameterChange(const pluginLib::Parameter& _parameter, const pluginLib::ParamValue _value) + { + const auto &desc = _parameter.getDescription(); - data.insert(std::make_pair(pluginLib::MidiDataType::Part, _parameter.getPart())); - data.insert(std::make_pair(pluginLib::MidiDataType::Page, desc.page)); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, desc.index)); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, v)); + std::map<pluginLib::MidiDataType, uint8_t> data; - sendSysEx(SingleParameterChange, data); -} + if (desc.page >= 100) + { + uint8_t v; -bool Controller::sendGlobalParameterChange(mqLib::GlobalParameter _param, uint8_t _value) -{ - const auto index = static_cast<uint32_t>(_param); + if (!combineParameterChange(v, g_midiPacketNames[MultiDump], _parameter, _value)) + return; - if(m_globalData[index] == _value) - return true; + const auto& dump = mqLib::State::Dumps[static_cast<int>(mqLib::State::DumpType::Multi)]; - std::map<pluginLib::MidiDataType, uint8_t> data; + uint32_t idx = desc.index; - data.insert(std::make_pair(pluginLib::MidiDataType::Page, index >> 7 )); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, index & 0x7f )); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, _value)); + if(desc.page > 100) + idx += (static_cast<uint32_t>(mqLib::MultiParameter::Inst1) - static_cast<uint32_t>(mqLib::MultiParameter::Inst0)) * (desc.page - 101); - m_globalData[index] = _value; + data.insert(std::make_pair(pluginLib::MidiDataType::Part, _parameter.getPart())); + data.insert(std::make_pair(pluginLib::MidiDataType::Page, idx >> 7)); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, idx & 0x7f)); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, v)); - return sendSysEx(GlobalParameterChange, data); -} + sendSysEx(MultiParameterChange, data); + return; + } -void Controller::requestSingle(mqLib::MidiBufferNum _buf, mqLib::MidiSoundLocation _location, uint8_t _locationOffset/* = 0*/) const -{ - std::map<pluginLib::MidiDataType, uint8_t> params; - params[pluginLib::MidiDataType::Bank] = static_cast<uint8_t>(_buf); - params[pluginLib::MidiDataType::Program] = static_cast<uint8_t>(_location) + _locationOffset; - sendSysEx(RequestSingle, params); -} + uint8_t v; + if (!combineParameterChange(v, g_midiPacketNames[SingleDump], _parameter, _value)) + return; -void Controller::requestMulti(mqLib::MidiBufferNum _buf, mqLib::MidiSoundLocation _location, uint8_t _locationOffset) const -{ - std::map<pluginLib::MidiDataType, uint8_t> params; - params[pluginLib::MidiDataType::Bank] = static_cast<uint8_t>(_buf); - params[pluginLib::MidiDataType::Program] = static_cast<uint8_t>(_location) + _locationOffset; - sendSysEx(RequestMulti, params); -} + data.insert(std::make_pair(pluginLib::MidiDataType::Part, _parameter.getPart())); + data.insert(std::make_pair(pluginLib::MidiDataType::Page, desc.page)); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, desc.index)); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, v)); -uint8_t Controller::getGlobalParam(mqLib::GlobalParameter _type) const -{ - return m_globalData[static_cast<uint32_t>(_type)]; -} + sendSysEx(SingleParameterChange, data); + } -bool Controller::isDerivedParameter(pluginLib::Parameter& _derived, pluginLib::Parameter& _base) const -{ - if(_derived.getDescription().page >= 100) - return false; + bool Controller::sendGlobalParameterChange(mqLib::GlobalParameter _param, uint8_t _value) + { + const auto index = static_cast<uint32_t>(_param); + + if(m_globalData[index] == _value) + return true; + + std::map<pluginLib::MidiDataType, uint8_t> data; + + data.insert(std::make_pair(pluginLib::MidiDataType::Page, index >> 7 )); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, index & 0x7f )); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, _value)); - const auto& packetName = g_midiPacketNames[SingleDump]; - const auto* packet = getMidiPacket(packetName); + m_globalData[index] = _value; - if (!packet) + return sendSysEx(GlobalParameterChange, data); + } + + void Controller::requestSingle(mqLib::MidiBufferNum _buf, mqLib::MidiSoundLocation _location, uint8_t _locationOffset/* = 0*/) const { - LOG("Failed to find midi packet " << packetName); - return true; + std::map<pluginLib::MidiDataType, uint8_t> params; + params[pluginLib::MidiDataType::Bank] = static_cast<uint8_t>(_buf); + params[pluginLib::MidiDataType::Program] = static_cast<uint8_t>(_location) + _locationOffset; + sendSysEx(RequestSingle, params); } - - const auto* defA = packet->getDefinitionByParameterName(_derived.getDescription().name); - const auto* defB = packet->getDefinitionByParameterName(_base.getDescription().name); - if (!defA || !defB) - return true; + void Controller::requestMulti(mqLib::MidiBufferNum _buf, mqLib::MidiSoundLocation _location, uint8_t _locationOffset) const + { + std::map<pluginLib::MidiDataType, uint8_t> params; + params[pluginLib::MidiDataType::Bank] = static_cast<uint8_t>(_buf); + params[pluginLib::MidiDataType::Program] = static_cast<uint8_t>(_location) + _locationOffset; + sendSysEx(RequestMulti, params); + } - return defA->doMasksOverlap(*defB); -} + uint8_t Controller::getGlobalParam(mqLib::GlobalParameter _type) const + { + return m_globalData[static_cast<uint32_t>(_type)]; + } -void Controller::requestAllPatches() const -{ - if (isMultiMode()) + bool Controller::isDerivedParameter(pluginLib::Parameter& _derived, pluginLib::Parameter& _base) const { - requestMulti(mqLib::MidiBufferNum::MultiEditBuffer, mqLib::MidiSoundLocation::EditBufferFirstMultiSingle); + if(_derived.getDescription().page >= 100) + return false; + + const auto& packetName = g_midiPacketNames[SingleDump]; + const auto* packet = getMidiPacket(packetName); - // the other singles 1-15 are requested one after the other after a single has been received - requestSingle(mqLib::MidiBufferNum::SingleEditBufferMultiMode, mqLib::MidiSoundLocation::EditBufferFirstMultiSingle, 0); + if (!packet) + { + LOG("Failed to find midi packet " << packetName); + return true; + } + + const auto* defA = packet->getDefinitionByParameterName(_derived.getDescription().name); + const auto* defB = packet->getDefinitionByParameterName(_base.getDescription().name); + + if (!defA || !defB) + return true; + + return defA->doMasksOverlap(*defB); } - else + + void Controller::requestAllPatches() const { - requestSingle(mqLib::MidiBufferNum::SingleEditBufferSingleMode, mqLib::MidiSoundLocation::EditBufferCurrentSingle); + if (isMultiMode()) + { + requestMulti(mqLib::MidiBufferNum::MultiEditBuffer, mqLib::MidiSoundLocation::EditBufferFirstMultiSingle); + + // the other singles 1-15 are requested one after the other after a single has been received + requestSingle(mqLib::MidiBufferNum::SingleEditBufferMultiMode, mqLib::MidiSoundLocation::EditBufferFirstMultiSingle, 0); + } + else + { + requestSingle(mqLib::MidiBufferNum::SingleEditBufferSingleMode, mqLib::MidiSoundLocation::EditBufferCurrentSingle); + } } } diff --git a/source/mqJucePlugin/mqController.h b/source/mqJucePlugin/mqController.h @@ -8,107 +8,107 @@ namespace mqJucePlugin { class FrontPanel; -} -class AudioPluginAudioProcessor; - -class Controller : public pluginLib::Controller -{ -public: - enum MidiPacketType - { - RequestSingle, - RequestMulti, - RequestDrum, - RequestSingleBank, - RequestMultiBank, - RequestDrumBank, - RequestGlobal, - RequestAllSingles, - SingleParameterChange, - MultiParameterChange, - GlobalParameterChange, - SingleDump, - SingleDumpQ, - MultiDump, - GlobalDump, - EmuRequestLcd, - EmuRequestLeds, - EmuSendButton, - EmuSendRotary, - - Count - }; - - struct Patch - { - std::string name; - std::vector<uint8_t> data; - }; - - pluginLib::Event<bool> onPlayModeChanged; - - Controller(AudioPluginAudioProcessor &, unsigned char _deviceId = 0); - ~Controller() override; - - void setFrontPanel(mqJucePlugin::FrontPanel* _frontPanel); - void sendSingle(const std::vector<uint8_t>& _sysex); - void sendSingle(const std::vector<uint8_t>& _sysex, uint8_t _part); - - bool sendSysEx(MidiPacketType _type) const; - bool sendSysEx(MidiPacketType _type, std::map<pluginLib::MidiDataType, uint8_t>& _params) const; - - bool isMultiMode() const; - void setPlayMode(bool _multiMode); - - void selectNextPreset(); - void selectPrevPreset(); - - std::vector<uint8_t> createSingleDump(mqLib::MidiBufferNum _buffer, mqLib::MidiSoundLocation _location, uint8_t _locationOffset, uint8_t _part) const; - std::vector<uint8_t> createSingleDump(mqLib::MidiBufferNum _buffer, mqLib::MidiSoundLocation _location, uint8_t _locationOffset, const pluginLib::MidiPacket - ::AnyPartParamValues& _values) const; - bool parseSingle(pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _paramValues, const std::vector<uint8_t>& _sysex) const; - - std::string getSingleName(const pluginLib::MidiPacket::ParamValues& _values) const; - std::string getSingleName(const pluginLib::MidiPacket::AnyPartParamValues& _values) const; - std::string getCategory(const pluginLib::MidiPacket::AnyPartParamValues& _values) const; - std::string getString(const pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, size_t _len) const; - - bool setSingleName(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const; - bool setCategory(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const; - bool setString(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, size_t _len, const std::string& _value) const; - -private: - void selectPreset(int _offset); - - static std::string loadParameterDescriptions(); - - void onStateLoaded() override; - - void parseSingle(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params); - void parseMulti(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params); - bool parseMidiPacket(MidiPacketType _type, pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _params, const pluginLib::SysEx& _sysex) const; - - bool parseSysexMessage(const pluginLib::SysEx&, synthLib::MidiEventSource _source) override; - bool parseControllerMessage(const synthLib::SMidiEvent&) override; - - void sendParameterChange(const pluginLib::Parameter& _parameter, pluginLib::ParamValue _value) override; - bool sendGlobalParameterChange(mqLib::GlobalParameter _param, uint8_t _value); - void requestSingle(mqLib::MidiBufferNum _buf, mqLib::MidiSoundLocation _location, uint8_t _locationOffset = 0) const; - void requestMulti(mqLib::MidiBufferNum _buf, mqLib::MidiSoundLocation _location, uint8_t _locationOffset = 0) const; - - uint8_t getGlobalParam(mqLib::GlobalParameter _type) const; - - bool isDerivedParameter(pluginLib::Parameter& _derived, pluginLib::Parameter& _base) const override; - - void requestAllPatches() const; - - const uint8_t m_deviceId; - - Patch m_singleEditBuffer; - std::array<Patch,16> m_singleEditBuffers; - std::array<uint8_t, 200> m_globalData{}; - mqJucePlugin::FrontPanel* m_frontPanel = nullptr; - std::array<uint32_t, 16> m_currentSingles{0}; - uint32_t m_currentSingle = 0; -}; + class AudioPluginAudioProcessor; + + class Controller : public pluginLib::Controller + { + public: + enum MidiPacketType + { + RequestSingle, + RequestMulti, + RequestDrum, + RequestSingleBank, + RequestMultiBank, + RequestDrumBank, + RequestGlobal, + RequestAllSingles, + SingleParameterChange, + MultiParameterChange, + GlobalParameterChange, + SingleDump, + SingleDumpQ, + MultiDump, + GlobalDump, + EmuRequestLcd, + EmuRequestLeds, + EmuSendButton, + EmuSendRotary, + + Count + }; + + struct Patch + { + std::string name; + std::vector<uint8_t> data; + }; + + pluginLib::Event<bool> onPlayModeChanged; + + Controller(AudioPluginAudioProcessor &, unsigned char _deviceId = 0); + ~Controller() override; + + void setFrontPanel(mqJucePlugin::FrontPanel* _frontPanel); + void sendSingle(const std::vector<uint8_t>& _sysex); + void sendSingle(const std::vector<uint8_t>& _sysex, uint8_t _part); + + bool sendSysEx(MidiPacketType _type) const; + bool sendSysEx(MidiPacketType _type, std::map<pluginLib::MidiDataType, uint8_t>& _params) const; + + bool isMultiMode() const; + void setPlayMode(bool _multiMode); + + void selectNextPreset(); + void selectPrevPreset(); + + std::vector<uint8_t> createSingleDump(mqLib::MidiBufferNum _buffer, mqLib::MidiSoundLocation _location, uint8_t _locationOffset, uint8_t _part) const; + std::vector<uint8_t> createSingleDump(mqLib::MidiBufferNum _buffer, mqLib::MidiSoundLocation _location, uint8_t _locationOffset, const pluginLib::MidiPacket + ::AnyPartParamValues& _values) const; + bool parseSingle(pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _paramValues, const std::vector<uint8_t>& _sysex) const; + + std::string getSingleName(const pluginLib::MidiPacket::ParamValues& _values) const; + std::string getSingleName(const pluginLib::MidiPacket::AnyPartParamValues& _values) const; + std::string getCategory(const pluginLib::MidiPacket::AnyPartParamValues& _values) const; + std::string getString(const pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, size_t _len) const; + + bool setSingleName(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const; + bool setCategory(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const; + bool setString(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, size_t _len, const std::string& _value) const; + + private: + void selectPreset(int _offset); + + static std::string loadParameterDescriptions(); + + void onStateLoaded() override; + + void parseSingle(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params); + void parseMulti(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params); + bool parseMidiPacket(MidiPacketType _type, pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _params, const pluginLib::SysEx& _sysex) const; + + bool parseSysexMessage(const pluginLib::SysEx&, synthLib::MidiEventSource _source) override; + bool parseControllerMessage(const synthLib::SMidiEvent&) override; + + void sendParameterChange(const pluginLib::Parameter& _parameter, pluginLib::ParamValue _value) override; + bool sendGlobalParameterChange(mqLib::GlobalParameter _param, uint8_t _value); + void requestSingle(mqLib::MidiBufferNum _buf, mqLib::MidiSoundLocation _location, uint8_t _locationOffset = 0) const; + void requestMulti(mqLib::MidiBufferNum _buf, mqLib::MidiSoundLocation _location, uint8_t _locationOffset = 0) const; + + uint8_t getGlobalParam(mqLib::GlobalParameter _type) const; + + bool isDerivedParameter(pluginLib::Parameter& _derived, pluginLib::Parameter& _base) const override; + + void requestAllPatches() const; + + const uint8_t m_deviceId; + + Patch m_singleEditBuffer; + std::array<Patch,16> m_singleEditBuffers; + std::array<uint8_t, 200> m_globalData{}; + mqJucePlugin::FrontPanel* m_frontPanel = nullptr; + std::array<uint32_t, 16> m_currentSingles{0}; + uint32_t m_currentSingle = 0; + }; +} +\ No newline at end of file diff --git a/source/mqJucePlugin/mqEditor.h b/source/mqJucePlugin/mqEditor.h @@ -2,9 +2,6 @@ #include "jucePluginEditorLib/pluginEditor.h" -class mqPartSelect; -class Controller; - namespace jucePluginEditorLib { class FocusedParameter; @@ -18,6 +15,8 @@ namespace pluginLib namespace mqJucePlugin { + class mqPartSelect; + class Controller; class FrontPanel; class PatchManager; diff --git a/source/mqJucePlugin/mqFrontPanel.h b/source/mqJucePlugin/mqFrontPanel.h @@ -7,10 +7,9 @@ #include "juce_gui_basics/juce_gui_basics.h" -class Controller; - namespace mqJucePlugin { + class Controller; class Editor; class FrontPanel diff --git a/source/mqJucePlugin/mqPartButton.cpp b/source/mqJucePlugin/mqPartButton.cpp @@ -2,18 +2,21 @@ #include "mqEditor.h" #include "mqPartSelect.h" -mqPartButton::mqPartButton(mqJucePlugin::Editor& _editor, const std::string& _name, ButtonStyle _buttonStyle) -: PartButton(_editor, _name, _buttonStyle) -, m_mqEditor(_editor) +namespace mqJucePlugin { -} + mqPartButton::mqPartButton(mqJucePlugin::Editor& _editor, const std::string& _name, ButtonStyle _buttonStyle) + : PartButton(_editor, _name, _buttonStyle) + , m_mqEditor(_editor) + { + } -bool mqPartButton::isInterestedInDragSource(const SourceDetails& dragSourceDetails) -{ - return PartButton<DrawableButton>::isInterestedInDragSource(dragSourceDetails); -} + bool mqPartButton::isInterestedInDragSource(const SourceDetails& dragSourceDetails) + { + return PartButton<DrawableButton>::isInterestedInDragSource(dragSourceDetails); + } -void mqPartButton::onClick() -{ - m_mqEditor.getPartSelect()->selectPart(getPart()); + void mqPartButton::onClick() + { + m_mqEditor.getPartSelect()->selectPart(getPart()); + } } diff --git a/source/mqJucePlugin/mqPartButton.h b/source/mqJucePlugin/mqPartButton.h @@ -2,22 +2,21 @@ #include "jucePluginEditorLib/partbutton.h" -class mqPartSelect; - namespace mqJucePlugin { class Editor; -} + class mqPartSelect; -class mqPartButton : public jucePluginEditorLib::PartButton<juce::DrawableButton> -{ -public: - explicit mqPartButton(mqJucePlugin::Editor& _editor, const std::string& _name, ButtonStyle _buttonStyle); + class mqPartButton : public jucePluginEditorLib::PartButton<juce::DrawableButton> + { + public: + explicit mqPartButton(Editor& _editor, const std::string& _name, ButtonStyle _buttonStyle); - bool isInterestedInDragSource(const SourceDetails& dragSourceDetails) override; + bool isInterestedInDragSource(const SourceDetails& dragSourceDetails) override; - void onClick() override; + void onClick() override; -private: - mqJucePlugin::Editor& m_mqEditor; -}; + private: + Editor& m_mqEditor; + }; +} diff --git a/source/mqJucePlugin/mqPartSelect.cpp b/source/mqJucePlugin/mqPartSelect.cpp @@ -4,71 +4,74 @@ #include "mqEditor.h" #include "mqPartButton.h" -mqPartSelect::mqPartSelect(mqJucePlugin::Editor& _editor, Controller& _controller, pluginLib::ParameterBinding& _parameterBinding) - : m_editor(_editor) - , m_controller(_controller) - , m_parameterBinding(_parameterBinding) +namespace mqJucePlugin { - std::vector<mqPartButton*> buttons; - std::vector<juce::Button*> leds; - - _editor.findComponents(buttons, "partSelectButton", 16); - _editor.findComponents(leds, "partSelectLED", 16); - - for(size_t i=0; i<m_parts.size(); ++i) + mqPartSelect::mqPartSelect(Editor& _editor, Controller& _controller, pluginLib::ParameterBinding& _parameterBinding) + : m_editor(_editor) + , m_controller(_controller) + , m_parameterBinding(_parameterBinding) { - auto& part = m_parts[i]; + std::vector<mqPartButton*> buttons; + std::vector<juce::Button*> leds; - part.button = buttons[i]; - part.led = leds[i]; + _editor.findComponents(buttons, "partSelectButton", 16); + _editor.findComponents(leds, "partSelectLED", 16); - auto index = static_cast<uint8_t>(i); + for(size_t i=0; i<m_parts.size(); ++i) + { + auto& part = m_parts[i]; - part.button->initalize(static_cast<uint8_t>(i)); + part.button = buttons[i]; + part.led = leds[i]; - part.led->onClick = [this, index] { selectPart(index); }; - } + auto index = static_cast<uint8_t>(i); - updateUiState(); -} + part.button->initalize(static_cast<uint8_t>(i)); -void mqPartSelect::onPlayModeChanged() const -{ - if(m_controller.getCurrentPart() > 0) - selectPart(0); - else - updateUiState(); -} + part.led->onClick = [this, index] { selectPart(index); }; + } -void mqPartSelect::updateUiState() const -{ - const auto current = m_controller.isMultiMode() ? m_controller.getCurrentPart() : static_cast<uint8_t>(0); + updateUiState(); + } - for(size_t i=0; i<m_parts.size(); ++i) + void mqPartSelect::onPlayModeChanged() const { - const auto& part = m_parts[i]; + if(m_controller.getCurrentPart() > 0) + selectPart(0); + else + updateUiState(); + } - part.button->setToggleState(i == current, juce::dontSendNotification); - part.led->setToggleState(i == current, juce::dontSendNotification); + void mqPartSelect::updateUiState() const + { + const auto current = m_controller.isMultiMode() ? m_controller.getCurrentPart() : static_cast<uint8_t>(0); - if(i > 0) + for(size_t i=0; i<m_parts.size(); ++i) { - part.button->setVisible(m_controller.isMultiMode()); - part.led->setVisible(m_controller.isMultiMode()); - /* - part.button->setEnabled(m_controller.isMultiMode()); - part.led->setEnabled(m_controller.isMultiMode()); - - part.button->setAlpha(1.0f); - part.led->setAlpha(1.0f); - */ + const auto& part = m_parts[i]; + + part.button->setToggleState(i == current, juce::dontSendNotification); + part.led->setToggleState(i == current, juce::dontSendNotification); + + if(i > 0) + { + part.button->setVisible(m_controller.isMultiMode()); + part.led->setVisible(m_controller.isMultiMode()); + /* + part.button->setEnabled(m_controller.isMultiMode()); + part.led->setEnabled(m_controller.isMultiMode()); + + part.button->setAlpha(1.0f); + part.led->setAlpha(1.0f); + */ + } } } -} -void mqPartSelect::selectPart(const uint8_t _index) const -{ - m_parameterBinding.setPart(_index); - m_editor.setCurrentPart(_index); - updateUiState(); + void mqPartSelect::selectPart(const uint8_t _index) const + { + m_parameterBinding.setPart(_index); + m_editor.setCurrentPart(_index); + updateUiState(); + } } diff --git a/source/mqJucePlugin/mqPartSelect.h b/source/mqJucePlugin/mqPartSelect.h @@ -2,35 +2,33 @@ #include "jucePluginLib/parameterbinding.h" -class mqPartButton; -class Controller; - namespace mqJucePlugin { + class mqPartButton; + class Controller; class Editor; -} -class mqPartSelect -{ -public: - explicit mqPartSelect(mqJucePlugin::Editor& _editor, Controller& _controller, pluginLib::ParameterBinding& _parameterBinding); + class mqPartSelect + { + public: + explicit mqPartSelect(mqJucePlugin::Editor& _editor, Controller& _controller, pluginLib::ParameterBinding& _parameterBinding); - void onPlayModeChanged() const; + void onPlayModeChanged() const; - void selectPart(uint8_t _index) const; + void selectPart(uint8_t _index) const; -private: - void updateUiState() const; + private: + void updateUiState() const; - struct Part - { - mqPartButton* button = nullptr; - juce::Button* led = nullptr; - }; - - mqJucePlugin::Editor& m_editor; - Controller& m_controller; - pluginLib::ParameterBinding& m_parameterBinding; - std::array<Part, 16> m_parts{}; -}; + struct Part + { + mqPartButton* button = nullptr; + juce::Button* led = nullptr; + }; + mqJucePlugin::Editor& m_editor; + Controller& m_controller; + pluginLib::ParameterBinding& m_parameterBinding; + std::array<Part, 16> m_parts{}; + }; +} diff --git a/source/mqJucePlugin/mqPatchManager.h b/source/mqJucePlugin/mqPatchManager.h @@ -2,10 +2,9 @@ #include "jucePluginEditorLib/patchmanager/patchmanager.h" -class Controller; - namespace mqJucePlugin { + class Controller; class Editor; class PatchManager : public jucePluginEditorLib::patchManager::PatchManager diff --git a/source/nord/n2x/n2xJucePlugin/n2xController.h b/source/nord/n2x/n2xJucePlugin/n2xController.h @@ -3,10 +3,10 @@ #include "jucePluginLib/controller.h" #include "n2xLib/n2xstate.h" -class AudioPluginAudioProcessor; - namespace n2xJucePlugin { + class AudioPluginAudioProcessor; + class Controller : public pluginLib::Controller { public: diff --git a/source/nord/n2x/n2xJucePlugin/n2xPluginEditorState.cpp b/source/nord/n2x/n2xJucePlugin/n2xPluginEditorState.cpp @@ -5,65 +5,68 @@ #include "synthLib/os.h" -const std::vector<PluginEditorState::Skin> g_includedSkins = +namespace n2xJucePlugin { - {"N2x", "n2xTrancy.json", ""}, -}; + const std::vector<PluginEditorState::Skin> g_includedSkins = + { + {"N2x", "n2xTrancy.json", ""}, + }; -PluginEditorState::PluginEditorState(AudioPluginAudioProcessor& _processor) : jucePluginEditorLib::PluginEditorState(_processor, _processor.getController(), g_includedSkins) -{ - loadDefaultSkin(); -} + PluginEditorState::PluginEditorState(AudioPluginAudioProcessor& _processor) : jucePluginEditorLib::PluginEditorState(_processor, _processor.getController(), g_includedSkins) + { + loadDefaultSkin(); + } -void PluginEditorState::initContextMenu(juce::PopupMenu& _menu) -{ - jucePluginEditorLib::PluginEditorState::initContextMenu(_menu); + void PluginEditorState::initContextMenu(juce::PopupMenu& _menu) + { + jucePluginEditorLib::PluginEditorState::initContextMenu(_menu); - auto& p = m_processor; + auto& p = m_processor; - const auto gain = static_cast<int>(std::roundf(p.getOutputGain())); + const auto gain = static_cast<int>(std::roundf(p.getOutputGain())); - juce::PopupMenu gainMenu; + juce::PopupMenu gainMenu; - gainMenu.addItem("0 dB (default)", true, gain == 1, [&p] { p.setOutputGain(1); }); - gainMenu.addItem("+6 dB", true, gain == 2, [&p] { p.setOutputGain(2); }); - gainMenu.addItem("+12 dB", true, gain == 4, [&p] { p.setOutputGain(4); }); + gainMenu.addItem("0 dB (default)", true, gain == 1, [&p] { p.setOutputGain(1); }); + gainMenu.addItem("+6 dB", true, gain == 2, [&p] { p.setOutputGain(2); }); + gainMenu.addItem("+12 dB", true, gain == 4, [&p] { p.setOutputGain(4); }); - _menu.addSubMenu("Output Gain", gainMenu); -} + _menu.addSubMenu("Output Gain", gainMenu); + } -bool PluginEditorState::initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) -{ - jucePluginEditorLib::PluginEditorState::initAdvancedContextMenu(_menu, _enabled); + bool PluginEditorState::initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) + { + jucePluginEditorLib::PluginEditorState::initAdvancedContextMenu(_menu, _enabled); - const auto percent = m_processor.getDspClockPercent(); - const auto hz = m_processor.getDspClockHz(); + const auto percent = m_processor.getDspClockPercent(); + const auto hz = m_processor.getDspClockHz(); - juce::PopupMenu clockMenu; + juce::PopupMenu clockMenu; - auto makeEntry = [&](const int _percent) - { - const auto mhz = hz * _percent / 100 / 1000000; - std::stringstream ss; - ss << _percent << "% (" << mhz << " MHz)"; - if(_percent == 100) - ss << " (Default)"; - clockMenu.addItem(ss.str(), _enabled, percent == _percent, [this, _percent] { m_processor.setDspClockPercent(_percent); }); - }; + auto makeEntry = [&](const int _percent) + { + const auto mhz = hz * _percent / 100 / 1000000; + std::stringstream ss; + ss << _percent << "% (" << mhz << " MHz)"; + if(_percent == 100) + ss << " (Default)"; + clockMenu.addItem(ss.str(), _enabled, percent == _percent, [this, _percent] { m_processor.setDspClockPercent(_percent); }); + }; - makeEntry(50); - makeEntry(75); - makeEntry(100); - makeEntry(125); - makeEntry(150); - makeEntry(200); + makeEntry(50); + makeEntry(75); + makeEntry(100); + makeEntry(125); + makeEntry(150); + makeEntry(200); - _menu.addSubMenu("DSP Clock", clockMenu); + _menu.addSubMenu("DSP Clock", clockMenu); - return true; -} + return true; + } -jucePluginEditorLib::Editor* PluginEditorState::createEditor(const Skin& _skin) -{ - return new n2xJucePlugin::Editor(m_processor, m_parameterBinding, _skin.folder, _skin.jsonFilename); + jucePluginEditorLib::Editor* PluginEditorState::createEditor(const Skin& _skin) + { + return new n2xJucePlugin::Editor(m_processor, m_parameterBinding, _skin.folder, _skin.jsonFilename); + } } diff --git a/source/nord/n2x/n2xJucePlugin/n2xPluginEditorState.h b/source/nord/n2x/n2xJucePlugin/n2xPluginEditorState.h @@ -7,14 +7,17 @@ namespace juce class Component; } -class AudioPluginAudioProcessor; - -class PluginEditorState : public jucePluginEditorLib::PluginEditorState +namespace n2xJucePlugin { -public: - explicit PluginEditorState(AudioPluginAudioProcessor& _processor); - void initContextMenu(juce::PopupMenu& _menu) override; - bool initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) override; -private: - jucePluginEditorLib::Editor* createEditor(const Skin& _skin) override; -}; + class AudioPluginAudioProcessor; + + class PluginEditorState : public jucePluginEditorLib::PluginEditorState + { + public: + explicit PluginEditorState(AudioPluginAudioProcessor& _processor); + void initContextMenu(juce::PopupMenu& _menu) override; + bool initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) override; + private: + jucePluginEditorLib::Editor* createEditor(const Skin& _skin) override; + }; +} diff --git a/source/nord/n2x/n2xJucePlugin/n2xPluginProcessor.cpp b/source/nord/n2x/n2xJucePlugin/n2xPluginProcessor.cpp @@ -9,8 +9,6 @@ #include "synthLib/deviceException.h" -class Controller; - namespace { juce::PropertiesFile::Options getOptions() @@ -24,42 +22,46 @@ namespace } } -//============================================================================== -AudioPluginAudioProcessor::AudioPluginAudioProcessor() : - Processor(BusesProperties() - .withOutput("Out AB", juce::AudioChannelSet::stereo(), true) - .withOutput("Out CD", juce::AudioChannelSet::stereo(), true) - , getOptions(), pluginLib::Processor::Properties{JucePlugin_Name, JucePlugin_IsSynth, JucePlugin_WantsMidiInput, JucePlugin_ProducesMidiOutput, JucePlugin_IsMidiEffect}) +namespace n2xJucePlugin { - getController(); - const auto latencyBlocks = getConfig().getIntValue("latencyBlocks", static_cast<int>(getPlugin().getLatencyBlocks())); - Processor::setLatencyBlocks(latencyBlocks); -} + class Controller; -AudioPluginAudioProcessor::~AudioPluginAudioProcessor() -{ - destroyEditorState(); -} + AudioPluginAudioProcessor::AudioPluginAudioProcessor() : + Processor(BusesProperties() + .withOutput("Out AB", juce::AudioChannelSet::stereo(), true) + .withOutput("Out CD", juce::AudioChannelSet::stereo(), true) + , getOptions(), pluginLib::Processor::Properties{JucePlugin_Name, JucePlugin_IsSynth, JucePlugin_WantsMidiInput, JucePlugin_ProducesMidiOutput, JucePlugin_IsMidiEffect}) + { + getController(); + const auto latencyBlocks = getConfig().getIntValue("latencyBlocks", static_cast<int>(getPlugin().getLatencyBlocks())); + Processor::setLatencyBlocks(latencyBlocks); + } -jucePluginEditorLib::PluginEditorState* AudioPluginAudioProcessor::createEditorState() -{ - return new PluginEditorState(*this); -} + AudioPluginAudioProcessor::~AudioPluginAudioProcessor() + { + destroyEditorState(); + } -synthLib::Device* AudioPluginAudioProcessor::createDevice() -{ - auto* d = new n2x::Device(); - if(!d->isValid()) - throw synthLib::DeviceException(synthLib::DeviceError::FirmwareMissing, "A firmware rom (512k .bin) is required, but was not found."); - return d; -} + jucePluginEditorLib::PluginEditorState* AudioPluginAudioProcessor::createEditorState() + { + return new PluginEditorState(*this); + } -pluginLib::Controller* AudioPluginAudioProcessor::createController() -{ - return new n2xJucePlugin::Controller(*this); + synthLib::Device* AudioPluginAudioProcessor::createDevice() + { + auto* d = new n2x::Device(); + if(!d->isValid()) + throw synthLib::DeviceException(synthLib::DeviceError::FirmwareMissing, "A firmware rom (512k .bin) is required, but was not found."); + return d; + } + + pluginLib::Controller* AudioPluginAudioProcessor::createController() + { + return new n2xJucePlugin::Controller(*this); + } } juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() { - return new AudioPluginAudioProcessor(); + return new n2xJucePlugin::AudioPluginAudioProcessor(); } diff --git a/source/nord/n2x/n2xJucePlugin/n2xPluginProcessor.h b/source/nord/n2x/n2xJucePlugin/n2xPluginProcessor.h @@ -2,16 +2,19 @@ #include "jucePluginEditorLib/pluginProcessor.h" -class AudioPluginAudioProcessor : public jucePluginEditorLib::Processor +namespace n2xJucePlugin { -public: - AudioPluginAudioProcessor(); - ~AudioPluginAudioProcessor() override; + class AudioPluginAudioProcessor : public jucePluginEditorLib::Processor + { + public: + AudioPluginAudioProcessor(); + ~AudioPluginAudioProcessor() override; - jucePluginEditorLib::PluginEditorState* createEditorState() override; - synthLib::Device* createDevice() override; - pluginLib::Controller* createController() override; + jucePluginEditorLib::PluginEditorState* createEditorState() override; + synthLib::Device* createDevice() override; + pluginLib::Controller* createController() override; -private: - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AudioPluginAudioProcessor) -}; + private: + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AudioPluginAudioProcessor) + }; +} diff --git a/source/osTIrusJucePlugin/OsTIrusEditorState.cpp b/source/osTIrusJucePlugin/OsTIrusEditorState.cpp @@ -6,6 +6,6 @@ const std::vector<jucePluginEditorLib::PluginEditorState::Skin> g_includedSkins {"TI Trancy", "VirusTI_Trancy.json", ""} }; -OsTIrusEditorState::OsTIrusEditorState(VirusProcessor& _processor, pluginLib::Controller& _controller) : VirusEditorState(_processor, _controller, g_includedSkins) +OsTIrusEditorState::OsTIrusEditorState(virus::VirusProcessor& _processor, pluginLib::Controller& _controller) : VirusEditorState(_processor, _controller, g_includedSkins) { } diff --git a/source/osTIrusJucePlugin/OsTIrusEditorState.h b/source/osTIrusJucePlugin/OsTIrusEditorState.h @@ -2,10 +2,8 @@ #include "virusJucePlugin/VirusEditorState.h" -class VirusProcessor; - -class OsTIrusEditorState : public VirusEditorState +class OsTIrusEditorState : public virus::VirusEditorState { public: - explicit OsTIrusEditorState(VirusProcessor& _processor, pluginLib::Controller& _controller); + explicit OsTIrusEditorState(virus::VirusProcessor& _processor, pluginLib::Controller& _controller); }; diff --git a/source/osTIrusJucePlugin/OsTIrusProcessor.h b/source/osTIrusJucePlugin/OsTIrusProcessor.h @@ -2,7 +2,7 @@ #include "virusJucePlugin/VirusProcessor.h" -class OsTIrusProcessor : public VirusProcessor +class OsTIrusProcessor : public virus::VirusProcessor { public: OsTIrusProcessor(); diff --git a/source/osirusJucePlugin/OsirusEditorState.cpp b/source/osirusJucePlugin/OsirusEditorState.cpp @@ -8,6 +8,6 @@ const std::vector<jucePluginEditorLib::PluginEditorState::Skin> g_includedSkins {"Galaxpel", "VirusC_Galaxpel.json", ""} }; -OsirusEditorState::OsirusEditorState(VirusProcessor& _processor, pluginLib::Controller& _controller) : VirusEditorState(_processor, _controller, g_includedSkins) +OsirusEditorState::OsirusEditorState(virus::VirusProcessor& _processor, pluginLib::Controller& _controller) : VirusEditorState(_processor, _controller, g_includedSkins) { } diff --git a/source/osirusJucePlugin/OsirusEditorState.h b/source/osirusJucePlugin/OsirusEditorState.h @@ -2,10 +2,8 @@ #include "virusJucePlugin/VirusEditorState.h" -class VirusProcessor; - -class OsirusEditorState : public VirusEditorState +class OsirusEditorState : public virus::VirusEditorState { public: - explicit OsirusEditorState(VirusProcessor& _processor, pluginLib::Controller& _controller); + explicit OsirusEditorState(virus::VirusProcessor& _processor, pluginLib::Controller& _controller); }; diff --git a/source/osirusJucePlugin/OsirusProcessor.h b/source/osirusJucePlugin/OsirusProcessor.h @@ -2,7 +2,7 @@ #include "virusJucePlugin/VirusProcessor.h" -class OsirusProcessor : public VirusProcessor +class OsirusProcessor : public virus::VirusProcessor { public: OsirusProcessor(); diff --git a/source/virusJucePlugin/FxPage.cpp b/source/virusJucePlugin/FxPage.cpp @@ -9,7 +9,7 @@ namespace genericVirusUI { FxPage::FxPage(const VirusEditor& _editor) { - const auto delayReverbMode = _editor.getController().getParameterIndexByName(Virus::g_paramDelayReverbMode); + const auto delayReverbMode = _editor.getController().getParameterIndexByName(virus::g_paramDelayReverbMode); const auto p = _editor.getController().getParamValueObject(delayReverbMode, 0); if(!p) diff --git a/source/virusJucePlugin/Leds.cpp b/source/virusJucePlugin/Leds.cpp @@ -10,7 +10,7 @@ namespace genericVirusUI constexpr const char* g_lfoNames[3] = {"Lfo1LedOn", "Lfo2LedOn", "Lfo3LedOn"}; - Leds::Leds(const genericUI::Editor& _editor, VirusProcessor& _processor) : m_processor(_processor), m_logoAnimationEnabled(_processor.getConfig().getBoolValue(g_logoAnimKey, true)) + Leds::Leds(const genericUI::Editor& _editor, virus::VirusProcessor& _processor) : m_processor(_processor), m_logoAnimationEnabled(_processor.getConfig().getBoolValue(g_logoAnimKey, true)) { for(size_t i=0; i<m_lfos.size(); ++i) { diff --git a/source/virusJucePlugin/Leds.h b/source/virusJucePlugin/Leds.h @@ -12,7 +12,10 @@ namespace juce class MouseListener; } -class VirusProcessor; +namespace virus +{ + class VirusProcessor; +} namespace genericUI { @@ -41,7 +44,7 @@ namespace genericVirusUI Leds& m_leds; }; - Leds(const genericUI::Editor& _editor, VirusProcessor& _processor); + Leds(const genericUI::Editor& _editor, virus::VirusProcessor& _processor); ~Leds(); void toggleLogoAnimation(); @@ -50,7 +53,7 @@ namespace genericVirusUI bool isLogoAnimationEnabled() const { return m_logoAnimationEnabled; } private: - VirusProcessor& m_processor; + virus::VirusProcessor& m_processor; bool m_logoAnimationEnabled = true; std::array<std::unique_ptr<jucePluginEditorLib::Led>, 3> m_lfos; diff --git a/source/virusJucePlugin/ParameterNames.h b/source/virusJucePlugin/ParameterNames.h @@ -1,6 +1,6 @@ #pragma once -namespace Virus +namespace virus { static constexpr char g_paramDelayReverbMode[] = "Delay/Reverb Mode"; static constexpr char g_paramPartVolume[] = "Part Volume"; diff --git a/source/virusJucePlugin/Parts.cpp b/source/virusJucePlugin/Parts.cpp @@ -46,8 +46,8 @@ namespace genericVirusUI m_presetName[i]->initalize(static_cast<uint8_t>(i)); - const auto partVolume = _editor.getController().getParameterIndexByName(Virus::g_paramPartVolume); - const auto partPanorama = _editor.getController().getParameterIndexByName(Virus::g_paramPartPanorama); + const auto partVolume = _editor.getController().getParameterIndexByName(virus::g_paramPartVolume); + const auto partPanorama = _editor.getController().getParameterIndexByName(virus::g_paramPartPanorama); _editor.getParameterBinding().bind(*m_partVolume[i], partVolume, static_cast<uint8_t>(i)); _editor.getParameterBinding().bind(*m_partPan[i], partPanorama, static_cast<uint8_t>(i)); @@ -170,7 +170,7 @@ namespace genericVirusUI { const auto multiMode = m_editor.getController().isMultiMode(); - const auto partCount = multiMode ? static_cast<VirusProcessor&>(m_editor.getProcessor()).getPartCount() : 1; + const auto partCount = multiMode ? static_cast<virus::VirusProcessor&>(m_editor.getProcessor()).getPartCount() : 1; for(size_t i=0; i<m_partSelect.size(); ++i) { @@ -189,7 +189,7 @@ namespace genericVirusUI m_presetName[i]->setVisible(visible); } - const auto volumeParam = m_editor.getController().getParameterIndexByName(multiMode ? Virus::g_paramPartVolume : Virus::g_paramPatchVolume); + const auto volumeParam = m_editor.getController().getParameterIndexByName(multiMode ? virus::g_paramPartVolume : virus::g_paramPatchVolume); m_editor.getParameterBinding().bind(*m_partVolume[0], volumeParam, 0); m_partVolume[0]->getProperties().set("parameter", static_cast<int>(volumeParam)); } diff --git a/source/virusJucePlugin/PatchManager.cpp b/source/virusJucePlugin/PatchManager.cpp @@ -15,7 +15,7 @@ #include "juce_cryptography/hashing/juce_MD5.h" -namespace Virus +namespace virus { class Controller; } @@ -98,7 +98,7 @@ namespace genericVirusUI if (_sysex.size() < 267) return nullptr; - const auto& c = static_cast<const Virus::Controller&>(m_controller); + const auto& c = static_cast<const virus::Controller&>(m_controller); pluginLib::MidiPacket::Data data; pluginLib::MidiPacket::AnyPartParamValues parameterValues; @@ -196,7 +196,7 @@ namespace genericVirusUI pluginLib::MidiPacket::Data data; pluginLib::MidiPacket::AnyPartParamValues parameterValues; - Virus::Controller::MidiPacketType usedPacketType; + virus::Controller::MidiPacketType usedPacketType; if (!m_controller.parseSingle(data, parameterValues, _patch->sysex, usedPacketType)) return _patch->sysex; diff --git a/source/virusJucePlugin/PatchManager.h b/source/virusJucePlugin/PatchManager.h @@ -5,7 +5,7 @@ #include "virusLib/microcontrollerTypes.h" -namespace Virus +namespace virus { class Controller; } @@ -37,6 +37,6 @@ namespace genericVirusUI void addRomPatches(); pluginLib::patchDB::DataSource createRomDataSource(uint32_t _bank) const; - Virus::Controller& m_controller; + virus::Controller& m_controller; }; } diff --git a/source/virusJucePlugin/VirusController.cpp b/source/virusJucePlugin/VirusController.cpp @@ -12,7 +12,7 @@ using MessageType = virusLib::SysexMessageType; -namespace Virus +namespace virus { constexpr const char* g_midiPacketNames[] = { diff --git a/source/virusJucePlugin/VirusController.h b/source/virusJucePlugin/VirusController.h @@ -7,12 +7,10 @@ #include "virusLib/microcontrollerTypes.h" #include "virusLib/romfile.h" -#include "synthLib/plugin.h" - -class VirusProcessor; - -namespace Virus +namespace virus { + class VirusProcessor; + class Controller : public pluginLib::Controller { public: diff --git a/source/virusJucePlugin/VirusEditor.cpp b/source/virusJucePlugin/VirusEditor.cpp @@ -16,7 +16,7 @@ namespace genericVirusUI { - VirusEditor::VirusEditor(pluginLib::ParameterBinding& _binding, VirusProcessor& _processorRef, const std::string& _jsonFilename, std::string _skinFolder) : + VirusEditor::VirusEditor(pluginLib::ParameterBinding& _binding, virus::VirusProcessor& _processorRef, const std::string& _jsonFilename, std::string _skinFolder) : Editor(_processorRef, _binding, std::move(_skinFolder)), m_processor(_processorRef), m_parameterBinding(_binding), @@ -180,9 +180,9 @@ namespace genericVirusUI getController().onProgramChange = nullptr; } - Virus::Controller& VirusEditor::getController() const + virus::Controller& VirusEditor::getController() const { - return static_cast<Virus::Controller&>(m_processor.getController()); + return static_cast<virus::Controller&>(m_processor.getController()); } const char* VirusEditor::findEmbeddedResource(const std::string& _filename, uint32_t& _size) const @@ -393,7 +393,7 @@ namespace genericVirusUI void VirusEditor::setPlayMode(uint8_t _playMode) { - const auto playMode = getController().getParameterIndexByName(Virus::g_paramPlayMode); + const auto playMode = getController().getParameterIndexByName(virus::g_paramPlayMode); auto* param = getController().getParameter(playMode); param->setUnnormalizedValueNotifyingHost(_playMode, pluginLib::Parameter::Origin::Ui); diff --git a/source/virusJucePlugin/VirusEditor.h b/source/virusJucePlugin/VirusEditor.h @@ -29,7 +29,10 @@ namespace pluginLib class ParameterBinding; } -class VirusProcessor; +namespace virus +{ + class VirusProcessor; +} namespace genericVirusUI { @@ -45,14 +48,14 @@ namespace genericVirusUI Arrangement }; - VirusEditor(pluginLib::ParameterBinding& _binding, VirusProcessor& _processorRef, const std::string& _jsonFilename, std::string _skinFolder); + VirusEditor(pluginLib::ParameterBinding& _binding, virus::VirusProcessor& _processorRef, const std::string& _jsonFilename, std::string _skinFolder); ~VirusEditor() override; void setPart(size_t _part); pluginLib::ParameterBinding& getParameterBinding() const { return m_parameterBinding; } - Virus::Controller& getController() const; + virus::Controller& getController() const; const char* findEmbeddedResource(const std::string& _filename, uint32_t& _size) const; const char* findResourceByFilename(const std::string& _filename, uint32_t& _size) override; @@ -84,7 +87,7 @@ namespace genericVirusUI void savePresets(SaveType _saveType, jucePluginEditorLib::FileType _fileType, uint8_t _bankNumber = 0); bool savePresets(const std::string& _pathName, SaveType _saveType, jucePluginEditorLib::FileType _fileType, uint8_t _bankNumber = 0) const; - VirusProcessor& m_processor; + virus::VirusProcessor& m_processor; pluginLib::ParameterBinding& m_parameterBinding; std::unique_ptr<Parts> m_parts; diff --git a/source/virusJucePlugin/VirusEditorState.cpp b/source/virusJucePlugin/VirusEditorState.cpp @@ -6,119 +6,122 @@ #include "synthLib/os.h" -VirusEditorState::VirusEditorState(VirusProcessor& _processor, pluginLib::Controller& _controller, const std::vector<VirusEditorState::Skin>& _includedSkins) - : jucePluginEditorLib::PluginEditorState(_processor, _controller, _includedSkins) +namespace virus { - loadDefaultSkin(); -} - -jucePluginEditorLib::Editor* VirusEditorState::createEditor(const Skin& _skin) -{ - return new genericVirusUI::VirusEditor(m_parameterBinding, static_cast<VirusProcessor&>(m_processor), _skin.jsonFilename, _skin.folder); -} + VirusEditorState::VirusEditorState(VirusProcessor& _processor, pluginLib::Controller& _controller, const std::vector<VirusEditorState::Skin>& _includedSkins) + : jucePluginEditorLib::PluginEditorState(_processor, _controller, _includedSkins) + { + loadDefaultSkin(); + } -void VirusEditorState::initContextMenu(juce::PopupMenu& _menu) -{ - jucePluginEditorLib::PluginEditorState::initContextMenu(_menu); - auto& p = m_processor; + jucePluginEditorLib::Editor* VirusEditorState::createEditor(const Skin& _skin) + { + return new genericVirusUI::VirusEditor(m_parameterBinding, static_cast<VirusProcessor&>(m_processor), _skin.jsonFilename, _skin.folder); + } + void VirusEditorState::initContextMenu(juce::PopupMenu& _menu) { - juce::PopupMenu gainMenu; + jucePluginEditorLib::PluginEditorState::initContextMenu(_menu); + auto& p = m_processor; - const auto gain = m_processor.getOutputGain(); + { + juce::PopupMenu gainMenu; - gainMenu.addItem("-12 dB", true, gain == 0.25f, [&p] { p.setOutputGain(0.25f); }); - gainMenu.addItem("-6 dB", true, gain == 0.5f, [&p] { p.setOutputGain(0.5f); }); - gainMenu.addItem("0 dB (default)", true, gain == 1, [&p] { p.setOutputGain(1); }); - gainMenu.addItem("+6 dB", true, gain == 2, [&p] { p.setOutputGain(2); }); - gainMenu.addItem("+12 dB", true, gain == 4, [&p] { p.setOutputGain(4); }); + const auto gain = m_processor.getOutputGain(); - _menu.addSubMenu("Output Gain", gainMenu); - } + gainMenu.addItem("-12 dB", true, gain == 0.25f, [&p] { p.setOutputGain(0.25f); }); + gainMenu.addItem("-6 dB", true, gain == 0.5f, [&p] { p.setOutputGain(0.5f); }); + gainMenu.addItem("0 dB (default)", true, gain == 1, [&p] { p.setOutputGain(1); }); + gainMenu.addItem("+6 dB", true, gain == 2, [&p] { p.setOutputGain(2); }); + gainMenu.addItem("+12 dB", true, gain == 4, [&p] { p.setOutputGain(4); }); - if(const auto* editor = dynamic_cast<genericVirusUI::VirusEditor*>(getEditor())) - { - const auto& leds = editor->getLeds(); + _menu.addSubMenu("Output Gain", gainMenu); + } - if(leds && leds->supportsLogoAnimation()) + if(const auto* editor = dynamic_cast<genericVirusUI::VirusEditor*>(getEditor())) { - _menu.addItem("Enable Logo Animation", true, leds->isLogoAnimationEnabled(), [this] + const auto& leds = editor->getLeds(); + + if(leds && leds->supportsLogoAnimation()) { - const auto* editor = dynamic_cast<genericVirusUI::VirusEditor*>(getEditor()); - if(editor) + _menu.addItem("Enable Logo Animation", true, leds->isLogoAnimationEnabled(), [this] { - const auto& leds = editor->getLeds(); - leds->toggleLogoAnimation(); - } - }); + const auto* editor = dynamic_cast<genericVirusUI::VirusEditor*>(getEditor()); + if(editor) + { + const auto& leds = editor->getLeds(); + leds->toggleLogoAnimation(); + } + }); + } } } -} -bool VirusEditorState::initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) -{ - jucePluginEditorLib::PluginEditorState::initAdvancedContextMenu(_menu, _enabled); + bool VirusEditorState::initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) + { + jucePluginEditorLib::PluginEditorState::initAdvancedContextMenu(_menu, _enabled); - const auto percent = m_processor.getDspClockPercent(); - const auto hz = m_processor.getDspClockHz(); + const auto percent = m_processor.getDspClockPercent(); + const auto hz = m_processor.getDspClockHz(); - juce::PopupMenu clockMenu; + juce::PopupMenu clockMenu; - auto makeEntry = [&](const int _percent) - { - const auto mhz = hz * _percent / 100 / 1000000; - std::stringstream ss; - ss << _percent << "% (" << mhz << " MHz)"; - if(_percent == 100) - ss << " (Default)"; - clockMenu.addItem(ss.str(), _enabled, percent == _percent, [this, _percent] { m_processor.setDspClockPercent(_percent); }); - }; - - makeEntry(50); - makeEntry(75); - makeEntry(100); - makeEntry(125); - makeEntry(150); - makeEntry(200); - - _menu.addSubMenu("DSP Clock", clockMenu); - - const auto samplerates = m_processor.getDeviceSupportedSamplerates(); - - if(samplerates.size() > 1) - { - juce::PopupMenu srMenu; + auto makeEntry = [&](const int _percent) + { + const auto mhz = hz * _percent / 100 / 1000000; + std::stringstream ss; + ss << _percent << "% (" << mhz << " MHz)"; + if(_percent == 100) + ss << " (Default)"; + clockMenu.addItem(ss.str(), _enabled, percent == _percent, [this, _percent] { m_processor.setDspClockPercent(_percent); }); + }; - const auto current = m_processor.getPreferredDeviceSamplerate(); + makeEntry(50); + makeEntry(75); + makeEntry(100); + makeEntry(125); + makeEntry(150); + makeEntry(200); - const auto preferred = m_processor.getDevicePreferredSamplerates(); + _menu.addSubMenu("DSP Clock", clockMenu); - srMenu.addItem("Automatic (Match with host)", true, current == 0.0f, [this] { m_processor.setPreferredDeviceSamplerate(0.0f); }); - srMenu.addSeparator(); - srMenu.addSectionHeader("Official, used automatically"); + const auto samplerates = m_processor.getDeviceSupportedSamplerates(); - auto addSRs = [&](bool _usePreferred) + if(samplerates.size() > 1) { - for (const float samplerate : samplerates) + juce::PopupMenu srMenu; + + const auto current = m_processor.getPreferredDeviceSamplerate(); + + const auto preferred = m_processor.getDevicePreferredSamplerates(); + + srMenu.addItem("Automatic (Match with host)", true, current == 0.0f, [this] { m_processor.setPreferredDeviceSamplerate(0.0f); }); + srMenu.addSeparator(); + srMenu.addSectionHeader("Official, used automatically"); + + auto addSRs = [&](bool _usePreferred) { - const auto isPreferred = std::find(preferred.begin(), preferred.end(), samplerate) != preferred.end(); + for (const float samplerate : samplerates) + { + const auto isPreferred = std::find(preferred.begin(), preferred.end(), samplerate) != preferred.end(); - if(isPreferred != _usePreferred) - continue; + if(isPreferred != _usePreferred) + continue; - const auto title = std::to_string(static_cast<int>(std::floor(samplerate + 0.5f))) + " Hz"; + const auto title = std::to_string(static_cast<int>(std::floor(samplerate + 0.5f))) + " Hz"; - srMenu.addItem(title, _enabled, std::fabs(samplerate - current) < 1.0f, [this, samplerate] { m_processor.setPreferredDeviceSamplerate(samplerate); }); - } - }; + srMenu.addItem(title, _enabled, std::fabs(samplerate - current) < 1.0f, [this, samplerate] { m_processor.setPreferredDeviceSamplerate(samplerate); }); + } + }; - addSRs(true); - srMenu.addSeparator(); - srMenu.addSectionHeader("Undocumented, use with care"); - addSRs(false); + addSRs(true); + srMenu.addSeparator(); + srMenu.addSectionHeader("Undocumented, use with care"); + addSRs(false); - _menu.addSubMenu("Device Samplerate", srMenu); - } + _menu.addSubMenu("Device Samplerate", srMenu); + } - return true; -} + return true; + } +} +\ No newline at end of file diff --git a/source/virusJucePlugin/VirusEditorState.h b/source/virusJucePlugin/VirusEditorState.h @@ -2,15 +2,18 @@ #include "jucePluginEditorLib/pluginEditorState.h" -class VirusProcessor; - -class VirusEditorState : public jucePluginEditorLib::PluginEditorState +namespace virus { -public: - explicit VirusEditorState(VirusProcessor& _processor, pluginLib::Controller& _controller, const std::vector<VirusEditorState::Skin>& _includedSkins); + class VirusProcessor; + + class VirusEditorState : public jucePluginEditorLib::PluginEditorState + { + public: + explicit VirusEditorState(VirusProcessor& _processor, pluginLib::Controller& _controller, const std::vector<VirusEditorState::Skin>& _includedSkins); - jucePluginEditorLib::Editor* createEditor(const Skin& _skin) override; + jucePluginEditorLib::Editor* createEditor(const Skin& _skin) override; - void initContextMenu(juce::PopupMenu& _menu) override; - bool initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) override; -}; + void initContextMenu(juce::PopupMenu& _menu) override; + bool initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) override; + }; +} +\ No newline at end of file diff --git a/source/virusJucePlugin/VirusProcessor.cpp b/source/virusJucePlugin/VirusProcessor.cpp @@ -9,127 +9,129 @@ #include "synthLib/deviceException.h" #include "synthLib/os.h" -//============================================================================== -VirusProcessor::VirusProcessor(const BusesProperties& _busesProperties, const juce::PropertiesFile::Options& _configOptions, const pluginLib::Processor::Properties& _properties, const std::vector<virusLib::ROMFile>& _roms, const virusLib::DeviceModel _defaultModel) - : Processor(_busesProperties, _configOptions, _properties) - , m_roms(_roms) - , m_defaultModel(_defaultModel) +namespace virus { -} - -VirusProcessor::~VirusProcessor() -{ - destroyController(); - destroyEditorState(); -} + VirusProcessor::VirusProcessor(const BusesProperties& _busesProperties, const juce::PropertiesFile::Options& _configOptions, const pluginLib::Processor::Properties& _properties, const std::vector<virusLib::ROMFile>& _roms, const virusLib::DeviceModel _defaultModel) + : Processor(_busesProperties, _configOptions, _properties) + , m_roms(_roms) + , m_defaultModel(_defaultModel) + { + } -//============================================================================== + VirusProcessor::~VirusProcessor() + { + destroyController(); + destroyEditorState(); + } -void VirusProcessor::processBpm(const float _bpm) -{ - // clamp to virus range, 63-190 - const auto bpmValue = juce::jmin(127, juce::jmax(0, static_cast<int>(_bpm)-63)); - const auto clockParam = getController().getParameter(m_clockTempoParam, 0); + //============================================================================== - if (clockParam == nullptr || clockParam->getUnnormalizedValue() == bpmValue) - return; + void VirusProcessor::processBpm(const float _bpm) + { + // clamp to virus range, 63-190 + const auto bpmValue = juce::jmin(127, juce::jmax(0, static_cast<int>(_bpm)-63)); + const auto clockParam = getController().getParameter(m_clockTempoParam, 0); - clockParam->setUnnormalizedValue(bpmValue, pluginLib::Parameter::Origin::HostAutomation); -} + if (clockParam == nullptr || clockParam->getUnnormalizedValue() == bpmValue) + return; -bool VirusProcessor::setSelectedRom(const uint32_t _index) -{ - if(_index >= m_roms.size()) - return false; - if(_index == m_selectedRom) - return true; - m_selectedRom = _index; + clockParam->setUnnormalizedValue(bpmValue, pluginLib::Parameter::Origin::HostAutomation); + } - try + bool VirusProcessor::setSelectedRom(const uint32_t _index) { - synthLib::Device* device = createDevice(); - getPlugin().setDevice(device); - (void)m_device.release(); - m_device.reset(device); + if(_index >= m_roms.size()) + return false; + if(_index == m_selectedRom) + return true; + m_selectedRom = _index; - evRomChanged.retain(getSelectedRom()); + try + { + synthLib::Device* device = createDevice(); + getPlugin().setDevice(device); + (void)m_device.release(); + m_device.reset(device); - return true; - } - catch(const synthLib::DeviceException& e) - { - juce::NativeMessageBox::showMessageBox(juce::MessageBoxIconType::WarningIcon, - "Device creation failed:", - std::string("Failed to create device:\n\n") + - e.what() + "\n\n" - "Will continue using old ROM"); - return false; - } -} + evRomChanged.retain(getSelectedRom()); -void VirusProcessor::postConstruct() -{ - evRomChanged.retain(getSelectedRom()); + return true; + } + catch(const synthLib::DeviceException& e) + { + juce::NativeMessageBox::showMessageBox(juce::MessageBoxIconType::WarningIcon, + "Device creation failed:", + std::string("Failed to create device:\n\n") + + e.what() + "\n\n" + "Will continue using old ROM"); + return false; + } + } - m_clockTempoParam = getController().getParameterIndexByName(Virus::g_paramClockTempo); + void VirusProcessor::postConstruct() + { + evRomChanged.retain(getSelectedRom()); - const auto latencyBlocks = getConfig().getIntValue("latencyBlocks", static_cast<int>(getPlugin().getLatencyBlocks())); - Processor::setLatencyBlocks(latencyBlocks); -} + m_clockTempoParam = getController().getParameterIndexByName(virus::g_paramClockTempo); -synthLib::Device* VirusProcessor::createDevice() -{ - const auto* rom = getSelectedRom(); + const auto latencyBlocks = getConfig().getIntValue("latencyBlocks", static_cast<int>(getPlugin().getLatencyBlocks())); + Processor::setLatencyBlocks(latencyBlocks); + } - if(!rom || !rom->isValid()) + synthLib::Device* VirusProcessor::createDevice() { - if(isTIFamily(m_defaultModel)) - throw synthLib::DeviceException(synthLib::DeviceError::FirmwareMissing, "A Virus TI firmware (.bin) is required, but was not found."); - throw synthLib::DeviceException(synthLib::DeviceError::FirmwareMissing, "A Virus A/B/C operating system (.bin or .mid) is required, but was not found."); + const auto* rom = getSelectedRom(); + + if(!rom || !rom->isValid()) + { + if(isTIFamily(m_defaultModel)) + throw synthLib::DeviceException(synthLib::DeviceError::FirmwareMissing, "A Virus TI firmware (.bin) is required, but was not found."); + throw synthLib::DeviceException(synthLib::DeviceError::FirmwareMissing, "A Virus A/B/C operating system (.bin or .mid) is required, but was not found."); + } + return new virusLib::Device(*rom, getPreferredDeviceSamplerate(), getHostSamplerate(), true); } - return new virusLib::Device(*rom, getPreferredDeviceSamplerate(), getHostSamplerate(), true); -} -pluginLib::Controller* VirusProcessor::createController() -{ - // force creation of device as the controller decides how to initialize based on the used ROM - getPlugin(); + pluginLib::Controller* VirusProcessor::createController() + { + // force creation of device as the controller decides how to initialize based on the used ROM + getPlugin(); - return new Virus::Controller(*this, m_defaultModel); -} + return new virus::Controller(*this, m_defaultModel); + } -void VirusProcessor::saveChunkData(baseLib::BinaryStream& s) -{ - auto* rom = getSelectedRom(); - if(rom) + void VirusProcessor::saveChunkData(baseLib::BinaryStream& s) { - baseLib::ChunkWriter cw(s, "ROM ", 2); - const auto romName = synthLib::getFilenameWithoutPath(rom->getFilename()); - s.write<uint8_t>(static_cast<uint8_t>(rom->getModel())); - s.write(romName); + auto* rom = getSelectedRom(); + if(rom) + { + baseLib::ChunkWriter cw(s, "ROM ", 2); + const auto romName = synthLib::getFilenameWithoutPath(rom->getFilename()); + s.write<uint8_t>(static_cast<uint8_t>(rom->getModel())); + s.write(romName); + } + Processor::saveChunkData(s); } - Processor::saveChunkData(s); -} -void VirusProcessor::loadChunkData(baseLib::ChunkReader& _cr) -{ - _cr.add("ROM ", 2, [this](baseLib::BinaryStream& _binaryStream, unsigned _version) + void VirusProcessor::loadChunkData(baseLib::ChunkReader& _cr) { - auto model = virusLib::DeviceModel::ABC; + _cr.add("ROM ", 2, [this](baseLib::BinaryStream& _binaryStream, unsigned _version) + { + auto model = virusLib::DeviceModel::ABC; - if(_version > 1) - model = static_cast<virusLib::DeviceModel>(_binaryStream.read<uint8_t>()); + if(_version > 1) + model = static_cast<virusLib::DeviceModel>(_binaryStream.read<uint8_t>()); - const auto romName = _binaryStream.readString(); + const auto romName = _binaryStream.readString(); - const auto& roms = getRoms(); - for(uint32_t i=0; i<static_cast<uint32_t>(roms.size()); ++i) - { - const auto& rom = roms[i]; - if(rom.getModel() == model && synthLib::getFilenameWithoutPath(rom.getFilename()) == romName) - setSelectedRom(i); - } - }); + const auto& roms = getRoms(); + for(uint32_t i=0; i<static_cast<uint32_t>(roms.size()); ++i) + { + const auto& rom = roms[i]; + if(rom.getModel() == model && synthLib::getFilenameWithoutPath(rom.getFilename()) == romName) + setSelectedRom(i); + } + }); - Processor::loadChunkData(_cr); -} + Processor::loadChunkData(_cr); + } +} +\ No newline at end of file diff --git a/source/virusJucePlugin/VirusProcessor.h b/source/virusJucePlugin/VirusProcessor.h @@ -9,73 +9,75 @@ #include "jucePluginEditorLib/pluginProcessor.h" -//============================================================================== -class VirusProcessor : public jucePluginEditorLib::Processor +namespace virus { -public: - VirusProcessor(const BusesProperties& _busesProperties, const juce::PropertiesFile::Options& _configOptions, const pluginLib::Processor::Properties& _properties, const std::vector<virusLib::ROMFile>& _roms, virusLib::DeviceModel _defaultModel); - ~VirusProcessor() override; + class VirusProcessor : public jucePluginEditorLib::Processor + { + public: + VirusProcessor(const BusesProperties& _busesProperties, const juce::PropertiesFile::Options& _configOptions, const pluginLib::Processor::Properties& _properties, const std::vector<virusLib::ROMFile>& _roms, virusLib::DeviceModel _defaultModel); + ~VirusProcessor() override; - void processBpm(float _bpm) override; + void processBpm(float _bpm) override; - // _____________ - // + // _____________ + // - std::string getRomName() const - { - const auto* rom = getSelectedRom(); - if(!rom) - return "<invalid>"; - return juce::File(juce::String(rom->getFilename())).getFileNameWithoutExtension().toStdString(); - } + std::string getRomName() const + { + const auto* rom = getSelectedRom(); + if(!rom) + return "<invalid>"; + return juce::File(juce::String(rom->getFilename())).getFileNameWithoutExtension().toStdString(); + } - const virusLib::ROMFile* getSelectedRom() const - { - if(m_selectedRom >= m_roms.size()) - return {}; - return &m_roms[m_selectedRom]; - } + const virusLib::ROMFile* getSelectedRom() const + { + if(m_selectedRom >= m_roms.size()) + return {}; + return &m_roms[m_selectedRom]; + } - virusLib::DeviceModel getModel() const - { - auto* rom = getSelectedRom(); - return rom ? rom->getModel() : virusLib::DeviceModel::Invalid; - } + virusLib::DeviceModel getModel() const + { + auto* rom = getSelectedRom(); + return rom ? rom->getModel() : virusLib::DeviceModel::Invalid; + } - const auto& getRoms() const { return m_roms; } + const auto& getRoms() const { return m_roms; } - bool setSelectedRom(uint32_t _index); - uint32_t getSelectedRomIndex() const { return m_selectedRom; } + bool setSelectedRom(uint32_t _index); + uint32_t getSelectedRomIndex() const { return m_selectedRom; } - uint32_t getPartCount() const - { - return getModel() == virusLib::DeviceModel::Snow ? 4 : 16; - } + uint32_t getPartCount() const + { + return getModel() == virusLib::DeviceModel::Snow ? 4 : 16; + } - virtual const char* findEmbeddedResource(const char* _name, uint32_t& _size) const = 0; + virtual const char* findEmbeddedResource(const char* _name, uint32_t& _size) const = 0; -protected: - void postConstruct(); + protected: + void postConstruct(); - // _____________ - // -private: - synthLib::Device* createDevice() override; + // _____________ + // + private: + synthLib::Device* createDevice() override; - pluginLib::Controller* createController() override; + pluginLib::Controller* createController() override; - void saveChunkData(baseLib::BinaryStream& s) override; - void loadChunkData(baseLib::ChunkReader& _cr) override; + void saveChunkData(baseLib::BinaryStream& s) override; + void loadChunkData(baseLib::ChunkReader& _cr) override; - //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VirusProcessor) + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VirusProcessor) - std::vector<virusLib::ROMFile> m_roms; - const virusLib::DeviceModel m_defaultModel; - uint32_t m_selectedRom = 0; + std::vector<virusLib::ROMFile> m_roms; + const virusLib::DeviceModel m_defaultModel; + uint32_t m_selectedRom = 0; - uint32_t m_clockTempoParam = 0xffffffff; + uint32_t m_clockTempoParam = 0xffffffff; -public: - pluginLib::Event<const virusLib::ROMFile*> evRomChanged; -}; + public: + pluginLib::Event<const virusLib::ROMFile*> evRomChanged; + }; +} diff --git a/source/xtJucePlugin/PluginEditorState.cpp b/source/xtJucePlugin/PluginEditorState.cpp @@ -5,66 +5,69 @@ #include "synthLib/os.h" -const std::vector<PluginEditorState::Skin> g_includedSkins = +namespace xtJucePlugin { - {"XT", "xtDefault.json", ""}, -}; + const std::vector<PluginEditorState::Skin> g_includedSkins = + { + {"XT", "xtDefault.json", ""}, + }; -PluginEditorState::PluginEditorState(AudioPluginAudioProcessor& _processor) : jucePluginEditorLib::PluginEditorState(_processor, _processor.getController(), g_includedSkins) -{ - loadDefaultSkin(); -} + PluginEditorState::PluginEditorState(AudioPluginAudioProcessor& _processor) : jucePluginEditorLib::PluginEditorState(_processor, _processor.getController(), g_includedSkins) + { + loadDefaultSkin(); + } -void PluginEditorState::initContextMenu(juce::PopupMenu& _menu) -{ - jucePluginEditorLib::PluginEditorState::initContextMenu(_menu); + void PluginEditorState::initContextMenu(juce::PopupMenu& _menu) + { + jucePluginEditorLib::PluginEditorState::initContextMenu(_menu); - auto& p = m_processor; + auto& p = m_processor; - const auto gain = static_cast<int>(std::roundf(p.getOutputGain())); + const auto gain = static_cast<int>(std::roundf(p.getOutputGain())); - juce::PopupMenu gainMenu; + juce::PopupMenu gainMenu; - gainMenu.addItem("0 dB (default)", true, gain == 1, [&p] { p.setOutputGain(1); }); - gainMenu.addItem("+6 dB", true, gain == 2, [&p] { p.setOutputGain(2); }); - gainMenu.addItem("+12 dB", true, gain == 4, [&p] { p.setOutputGain(4); }); + gainMenu.addItem("0 dB (default)", true, gain == 1, [&p] { p.setOutputGain(1); }); + gainMenu.addItem("+6 dB", true, gain == 2, [&p] { p.setOutputGain(2); }); + gainMenu.addItem("+12 dB", true, gain == 4, [&p] { p.setOutputGain(4); }); - _menu.addSubMenu("Output Gain", gainMenu); -} + _menu.addSubMenu("Output Gain", gainMenu); + } -bool PluginEditorState::initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) -{ - jucePluginEditorLib::PluginEditorState::initAdvancedContextMenu(_menu, _enabled); + bool PluginEditorState::initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) + { + jucePluginEditorLib::PluginEditorState::initAdvancedContextMenu(_menu, _enabled); - const auto percent = m_processor.getDspClockPercent(); - const auto hz = m_processor.getDspClockHz(); + const auto percent = m_processor.getDspClockPercent(); + const auto hz = m_processor.getDspClockHz(); - juce::PopupMenu clockMenu; + juce::PopupMenu clockMenu; - auto makeEntry = [&](const int _percent) - { - const auto mhz = hz * _percent / 100 / 1000000; - std::stringstream ss; - ss << _percent << "% (" << mhz << " MHz)"; - if(_percent == 100) - ss << " (Default)"; - clockMenu.addItem(ss.str(), _enabled, percent == _percent, [this, _percent] { m_processor.setDspClockPercent(_percent); }); - }; + auto makeEntry = [&](const int _percent) + { + const auto mhz = hz * _percent / 100 / 1000000; + std::stringstream ss; + ss << _percent << "% (" << mhz << " MHz)"; + if(_percent == 100) + ss << " (Default)"; + clockMenu.addItem(ss.str(), _enabled, percent == _percent, [this, _percent] { m_processor.setDspClockPercent(_percent); }); + }; - makeEntry(50); - makeEntry(75); - makeEntry(100); - makeEntry(125); - makeEntry(150); - makeEntry(200); + makeEntry(50); + makeEntry(75); + makeEntry(100); + makeEntry(125); + makeEntry(150); + makeEntry(200); - _menu.addSubMenu("DSP Clock", clockMenu); + _menu.addSubMenu("DSP Clock", clockMenu); - return true; -} + return true; + } -jucePluginEditorLib::Editor* PluginEditorState::createEditor(const Skin& _skin) -{ - return new xtJucePlugin::Editor(m_processor, m_parameterBinding, _skin.folder, _skin.jsonFilename); -} + jucePluginEditorLib::Editor* PluginEditorState::createEditor(const Skin& _skin) + { + return new xtJucePlugin::Editor(m_processor, m_parameterBinding, _skin.folder, _skin.jsonFilename); + } +} +\ No newline at end of file diff --git a/source/xtJucePlugin/PluginEditorState.h b/source/xtJucePlugin/PluginEditorState.h @@ -7,14 +7,17 @@ namespace juce class Component; } -class AudioPluginAudioProcessor; - -class PluginEditorState : public jucePluginEditorLib::PluginEditorState +namespace xtJucePlugin { -public: - explicit PluginEditorState(AudioPluginAudioProcessor& _processor); - void initContextMenu(juce::PopupMenu& _menu) override; - bool initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) override; -private: - jucePluginEditorLib::Editor* createEditor(const Skin& _skin) override; -}; + class AudioPluginAudioProcessor; + + class PluginEditorState : public jucePluginEditorLib::PluginEditorState + { + public: + explicit PluginEditorState(AudioPluginAudioProcessor& _processor); + void initContextMenu(juce::PopupMenu& _menu) override; + bool initAdvancedContextMenu(juce::PopupMenu& _menu, bool _enabled) override; + private: + jucePluginEditorLib::Editor* createEditor(const Skin& _skin) override; + }; +} diff --git a/source/xtJucePlugin/PluginProcessor.cpp b/source/xtJucePlugin/PluginProcessor.cpp @@ -21,44 +21,44 @@ namespace } } -//============================================================================== -AudioPluginAudioProcessor::AudioPluginAudioProcessor() : - Processor(BusesProperties() - .withInput("Input", juce::AudioChannelSet::stereo(), true) - .withOutput("Output", juce::AudioChannelSet::stereo(), true) +namespace xtJucePlugin +{ + AudioPluginAudioProcessor::AudioPluginAudioProcessor() : + Processor(BusesProperties() + .withInput("Input", juce::AudioChannelSet::stereo(), true) + .withOutput("Output", juce::AudioChannelSet::stereo(), true) #if JucePlugin_IsSynth - .withOutput("Out 2", juce::AudioChannelSet::stereo(), true) + .withOutput("Out 2", juce::AudioChannelSet::stereo(), true) #endif - , getOptions(), pluginLib::Processor::Properties{JucePlugin_Name, JucePlugin_IsSynth, JucePlugin_WantsMidiInput, JucePlugin_ProducesMidiOutput, JucePlugin_IsMidiEffect}) -{ - getController(); - const auto latencyBlocks = getConfig().getIntValue("latencyBlocks", static_cast<int>(getPlugin().getLatencyBlocks())); - Processor::setLatencyBlocks(latencyBlocks); -} + , getOptions(), pluginLib::Processor::Properties{JucePlugin_Name, JucePlugin_IsSynth, JucePlugin_WantsMidiInput, JucePlugin_ProducesMidiOutput, JucePlugin_IsMidiEffect}) + { + getController(); + const auto latencyBlocks = getConfig().getIntValue("latencyBlocks", static_cast<int>(getPlugin().getLatencyBlocks())); + Processor::setLatencyBlocks(latencyBlocks); + } -AudioPluginAudioProcessor::~AudioPluginAudioProcessor() -{ - destroyEditorState(); -} + AudioPluginAudioProcessor::~AudioPluginAudioProcessor() + { + destroyEditorState(); + } -jucePluginEditorLib::PluginEditorState* AudioPluginAudioProcessor::createEditorState() -{ - return new PluginEditorState(*this); -} + jucePluginEditorLib::PluginEditorState* AudioPluginAudioProcessor::createEditorState() + { + return new PluginEditorState(*this); + } -synthLib::Device* AudioPluginAudioProcessor::createDevice() -{ - return new xt::Device(); -} + synthLib::Device* AudioPluginAudioProcessor::createDevice() + { + return new xt::Device(); + } -pluginLib::Controller* AudioPluginAudioProcessor::createController() -{ - return new Controller(*this); + pluginLib::Controller* AudioPluginAudioProcessor::createController() + { + return new Controller(*this); + } } -//============================================================================== -// This creates new instances of the plugin.. juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() { - return new AudioPluginAudioProcessor(); + return new xtJucePlugin::AudioPluginAudioProcessor(); } diff --git a/source/xtJucePlugin/PluginProcessor.h b/source/xtJucePlugin/PluginProcessor.h @@ -2,22 +2,21 @@ #include "jucePluginEditorLib/pluginProcessor.h" -//============================================================================== -class AudioPluginAudioProcessor : public jucePluginEditorLib::Processor +namespace xtJucePlugin { -public: - AudioPluginAudioProcessor(); - ~AudioPluginAudioProcessor() override; + class AudioPluginAudioProcessor : public jucePluginEditorLib::Processor + { + public: + AudioPluginAudioProcessor(); + ~AudioPluginAudioProcessor() override; - jucePluginEditorLib::PluginEditorState* createEditorState() override; - // _____________ - // - synthLib::Device* createDevice() override; + jucePluginEditorLib::PluginEditorState* createEditorState() override; - pluginLib::Controller* createController() override; + synthLib::Device* createDevice() override; -private: + pluginLib::Controller* createController() override; - //============================================================================== - JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AudioPluginAudioProcessor) -}; + private: + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AudioPluginAudioProcessor) + }; +} diff --git a/source/xtJucePlugin/weData.h b/source/xtJucePlugin/weData.h @@ -12,10 +12,10 @@ #include "jucePluginLib/midipacket.h" #include "jucePluginLib/event.h" -class Controller; - namespace xtJucePlugin { + class Controller; + class WaveEditorData { public: diff --git a/source/xtJucePlugin/xtController.cpp b/source/xtJucePlugin/xtController.cpp @@ -42,9 +42,9 @@ namespace "tableDump" }; - static_assert(std::size(g_midiPacketNames) == static_cast<size_t>(Controller::MidiPacketType::Count)); + static_assert(std::size(g_midiPacketNames) == static_cast<size_t>(xtJucePlugin::Controller::MidiPacketType::Count)); - const char* midiPacketName(Controller::MidiPacketType _type) + const char* midiPacketName(xtJucePlugin::Controller::MidiPacketType _type) { return g_midiPacketNames[static_cast<uint32_t>(_type)]; } @@ -63,657 +63,660 @@ namespace constexpr uint32_t g_pageControllers = 40; } -Controller::Controller(AudioPluginAudioProcessor& p, unsigned char _deviceId) : pluginLib::Controller(p, loadParameterDescriptions()), m_deviceId(_deviceId) +namespace xtJucePlugin { - registerParams(p); + Controller::Controller(AudioPluginAudioProcessor& p, const unsigned char _deviceId) : pluginLib::Controller(p, loadParameterDescriptions()), m_deviceId(_deviceId) + { + registerParams(p); - sendSysEx(RequestGlobal); - sendSysEx(RequestMode); - requestMulti(xt::LocationH::MultiDumpMultiEditBuffer, 0); + sendSysEx(RequestGlobal); + sendSysEx(RequestMode); + requestMulti(xt::LocationH::MultiDumpMultiEditBuffer, 0); - onPlayModeChanged.addListener([this](bool multiMode) - { - requestAllPatches(); - }); + onPlayModeChanged.addListener([this](bool multiMode) + { + requestAllPatches(); + }); - // slow down edits of the wavetable, device gets overloaded quickly if we send too many changes - uint32_t idx; - getParameterDescriptions().getIndexByName(idx, "Wave"); - for(uint8_t i=0; i<m_singleEditBuffers.size(); ++i) - { - auto* p = getParameter(idx, i); - p->setRateLimitMilliseconds(250); + // slow down edits of the wavetable, device gets overloaded quickly if we send too many changes + uint32_t idx; + getParameterDescriptions().getIndexByName(idx, "Wave"); + for(uint8_t i=0; i<m_singleEditBuffers.size(); ++i) + { + auto* p = getParameter(idx, i); + p->setRateLimitMilliseconds(250); + } } -} -Controller::~Controller() = default; + Controller::~Controller() = default; -bool Controller::sendSingle(const std::vector<uint8_t>& _sysex) -{ - return sendSingle(_sysex, getCurrentPart()); -} + bool Controller::sendSingle(const std::vector<uint8_t>& _sysex) + { + return sendSingle(_sysex, getCurrentPart()); + } -bool Controller::sendSingle(const std::vector<uint8_t>& _sysex, const uint8_t _part) -{ - if(_sysex.size() == xt::Mw1::g_singleDumpLength) + bool Controller::sendSingle(const std::vector<uint8_t>& _sysex, const uint8_t _part) { - // No program/bank bytes are part of the dump, send as-is and request the result + if(_sysex.size() == xt::Mw1::g_singleDumpLength) + { + // No program/bank bytes are part of the dump, send as-is and request the result - if(_part > 0) - return false; // we cannot support this as the hardware loads a MW1 to the "current" instrument, which is always the first one + if(_part > 0) + return false; // we cannot support this as the hardware loads a MW1 to the "current" instrument, which is always the first one + + pluginLib::Controller::sendSysEx(_sysex); + requestSingle(isMultiMode() ? xt::LocationH::SingleEditBufferMultiMode : xt::LocationH::SingleEditBufferSingleMode, 0); + return true; + } + + auto data = _sysex; + + data[wLib::IdxBuffer] = static_cast<uint8_t>(isMultiMode() ? xt::LocationH::SingleEditBufferMultiMode : xt::LocationH::SingleEditBufferSingleMode); + data[wLib::IdxLocation] = isMultiMode() ? _part : 0; + data[wLib::IdxDeviceId] = m_deviceId; + + const auto* p = getMidiPacket(g_midiPacketNames[SingleDump]); + + if (!p->updateChecksums(data)) + return false; + + pluginLib::Controller::sendSysEx(data); + + sendLockedParameters(_part); - pluginLib::Controller::sendSysEx(_sysex); requestSingle(isMultiMode() ? xt::LocationH::SingleEditBufferMultiMode : xt::LocationH::SingleEditBufferSingleMode, 0); + return true; } - auto data = _sysex; + const char* findEmbeddedResource(const std::string& _filename, uint32_t& _size) + { + for(size_t i=0; i<BinaryData::namedResourceListSize; ++i) + { + if (BinaryData::originalFilenames[i] != _filename) + continue; - data[wLib::IdxBuffer] = static_cast<uint8_t>(isMultiMode() ? xt::LocationH::SingleEditBufferMultiMode : xt::LocationH::SingleEditBufferSingleMode); - data[wLib::IdxLocation] = isMultiMode() ? _part : 0; - data[wLib::IdxDeviceId] = m_deviceId; + int size = 0; + const auto res = BinaryData::getNamedResource(BinaryData::namedResourceList[i], size); + _size = static_cast<uint32_t>(size); + return res; + } + return nullptr; + } - const auto* p = getMidiPacket(g_midiPacketNames[SingleDump]); + std::string Controller::loadParameterDescriptions() + { + const auto name = "parameterDescriptions_xt.json"; + const auto path = synthLib::getModulePath() + name; - if (!p->updateChecksums(data)) - return false; + const std::ifstream f(path.c_str(), std::ios::in); + if(f.is_open()) + { + std::stringstream buf; + buf << f.rdbuf(); + return buf.str(); + } + + uint32_t size; + const auto res = findEmbeddedResource(name, size); + if(res) + return {res, size}; + return {}; + } - pluginLib::Controller::sendSysEx(data); + void Controller::onStateLoaded() + { + } - sendLockedParameters(_part); + uint8_t Controller::getPartCount() const + { + return 8; + } - requestSingle(isMultiMode() ? xt::LocationH::SingleEditBufferMultiMode : xt::LocationH::SingleEditBufferSingleMode, 0); + std::string Controller::getSingleName(const pluginLib::MidiPacket::ParamValues& _values) const + { + std::string name; + for(uint32_t i=0; i<16; ++i) + { + char paramName[16]; + (void)snprintf(paramName, sizeof(paramName), "Name%02u", i); + const auto idx = getParameterIndexByName(paramName); + if(idx == InvalidParameterIndex) + break; - return true; -} + const auto it = _values.find(std::make_pair(pluginLib::MidiPacket::AnyPart, idx)); + if(it == _values.end()) + break; -const char* findEmbeddedResource(const std::string& _filename, uint32_t& _size) -{ - for(size_t i=0; i<BinaryData::namedResourceListSize; ++i) + name += static_cast<char>(it->second); + } + return name; + } + + std::string Controller::getSingleName(const uint8_t _part) const { - if (BinaryData::originalFilenames[i] != _filename) - continue; + std::string name; + for(uint32_t i=0; i<16; ++i) + { + char paramName[16]; + (void)snprintf(paramName, sizeof(paramName), "Name%02u", i); + const auto idx = getParameterIndexByName(paramName); + if(idx == InvalidParameterIndex) + break; - int size = 0; - const auto res = BinaryData::getNamedResource(BinaryData::namedResourceList[i], size); - _size = static_cast<uint32_t>(size); - return res; - } - return nullptr; -} + const auto* p = getParameter(idx, _part); + if(!p) + break; -std::string Controller::loadParameterDescriptions() -{ - const auto name = "parameterDescriptions_xt.json"; - const auto path = synthLib::getModulePath() + name; - - const std::ifstream f(path.c_str(), std::ios::in); - if(f.is_open()) - { - std::stringstream buf; - buf << f.rdbuf(); - return buf.str(); - } - - uint32_t size; - const auto res = findEmbeddedResource(name, size); - if(res) - return {res, size}; - return {}; -} + name += static_cast<char>(p->getUnnormalizedValue()); + } + return name; + } -void Controller::onStateLoaded() -{ -} + std::string Controller::getSingleName(const pluginLib::MidiPacket::AnyPartParamValues& _values) const + { + return getString(_values, "Name", 16); + } -uint8_t Controller::getPartCount() const -{ - return 8; -} + std::string Controller::getString(const pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, const size_t _len) const + { + std::string name; + for(uint32_t i=0; i<_len; ++i) + { + char paramName[64]; + (void)snprintf(paramName, sizeof(paramName), "%s%02u", _prefix.c_str(), i); -std::string Controller::getSingleName(const pluginLib::MidiPacket::ParamValues& _values) const -{ - std::string name; - for(uint32_t i=0; i<16; ++i) - { - char paramName[16]; - (void)snprintf(paramName, sizeof(paramName), "Name%02u", i); - const auto idx = getParameterIndexByName(paramName); - if(idx == InvalidParameterIndex) - break; - - const auto it = _values.find(std::make_pair(pluginLib::MidiPacket::AnyPart, idx)); - if(it == _values.end()) - break; - - name += static_cast<char>(it->second); - } - return name; -} + const auto idx = getParameterIndexByName(paramName); + if(idx == InvalidParameterIndex) + break; -std::string Controller::getSingleName(const uint8_t _part) const -{ - std::string name; - for(uint32_t i=0; i<16; ++i) - { - char paramName[16]; - (void)snprintf(paramName, sizeof(paramName), "Name%02u", i); - const auto idx = getParameterIndexByName(paramName); - if(idx == InvalidParameterIndex) - break; - - const auto* p = getParameter(idx, _part); - if(!p) - break; - - name += static_cast<char>(p->getUnnormalizedValue()); - } - return name; -} + const auto it = _values[idx]; + if(!it) + break; -std::string Controller::getSingleName(const pluginLib::MidiPacket::AnyPartParamValues& _values) const -{ - return getString(_values, "Name", 16); -} + name += static_cast<char>(*it); + } + return name; + } -std::string Controller::getString(const pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, const size_t _len) const -{ - std::string name; - for(uint32_t i=0; i<_len; ++i) - { - char paramName[64]; - (void)snprintf(paramName, sizeof(paramName), "%s%02u", _prefix.c_str(), i); - - const auto idx = getParameterIndexByName(paramName); - if(idx == InvalidParameterIndex) - break; - - const auto it = _values[idx]; - if(!it) - break; - - name += static_cast<char>(*it); - } - return name; -} + bool Controller::setSingleName(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const + { + return setString(_values, "Name", 16, _value); + } -bool Controller::setSingleName(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const -{ - return setString(_values, "Name", 16, _value); -} + void Controller::parseSingle(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params) + { + Patch patch; + patch.data = _msg; + patch.name = getSingleName(_params); -void Controller::parseSingle(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params) -{ - Patch patch; - patch.data = _msg; - patch.name = getSingleName(_params); + const auto bank = _data.at(pluginLib::MidiDataType::Bank); + const auto prog = _data.at(pluginLib::MidiDataType::Program); - const auto bank = _data.at(pluginLib::MidiDataType::Bank); - const auto prog = _data.at(pluginLib::MidiDataType::Program); + if(bank == static_cast<uint8_t>(xt::LocationH::SingleEditBufferSingleMode) && prog == 0) + { + m_singleEditBuffer = patch; - if(bank == static_cast<uint8_t>(xt::LocationH::SingleEditBufferSingleMode) && prog == 0) - { - m_singleEditBuffer = patch; + if(!isMultiMode()) + applyPatchParameters(_params, 0); + } + else if(bank == static_cast<uint8_t>(xt::LocationH::SingleEditBufferMultiMode)) + { + m_singleEditBuffers[prog] = patch; - if(!isMultiMode()) - applyPatchParameters(_params, 0); - } - else if(bank == static_cast<uint8_t>(xt::LocationH::SingleEditBufferMultiMode)) - { - m_singleEditBuffers[prog] = patch; + if (isMultiMode()) + applyPatchParameters(_params, prog); - if (isMultiMode()) - applyPatchParameters(_params, prog); + // if we switched to multi, all singles have to be requested. However, we cannot send all requests at once (device will miss some) + // so we chain them one after the other + if(prog + 1 < m_singleEditBuffers.size()) + requestSingle(xt::LocationH::SingleEditBufferMultiMode, prog + 1); + } - // if we switched to multi, all singles have to be requested. However, we cannot send all requests at once (device will miss some) - // so we chain them one after the other - if(prog + 1 < m_singleEditBuffers.size()) - requestSingle(xt::LocationH::SingleEditBufferMultiMode, prog + 1); - } + onProgramChanged(prog); + } - onProgramChanged(prog); -} + void Controller::parseMulti(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params) const + { + Patch patch; + patch.data = _msg; + patch.name = getSingleName(_params); -void Controller::parseMulti(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params) const -{ - Patch patch; - patch.data = _msg; - patch.name = getSingleName(_params); + const auto bank = _data.at(pluginLib::MidiDataType::Bank); + // const auto prog = _data.at(pluginLib::MidiDataType::Program); - const auto bank = _data.at(pluginLib::MidiDataType::Bank); -// const auto prog = _data.at(pluginLib::MidiDataType::Program); + if(bank == static_cast<uint8_t>(xt::LocationH::MultiDumpMultiEditBuffer)) + { + applyPatchParameters(_params, 0); + } + } - if(bank == static_cast<uint8_t>(xt::LocationH::MultiDumpMultiEditBuffer)) + void Controller::parseGlobal(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params) { + memcpy(m_globalData.data(), &_msg[xt::IdxGlobalParamFirst], sizeof(m_globalData)); + applyPatchParameters(_params, 0); } -} -void Controller::parseGlobal(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params) -{ - memcpy(m_globalData.data(), &_msg[xt::IdxGlobalParamFirst], sizeof(m_globalData)); + bool Controller::parseSysexMessage(const pluginLib::SysEx& _msg, synthLib::MidiEventSource) + { + if(_msg.size() >= 5) + { + switch (const auto cmd = static_cast<xt::SysexCommand>(_msg[4])) + { + case xt::SysexCommand::EmuRotaries: + case xt::SysexCommand::EmuButtons: + case xt::SysexCommand::EmuLCD: + case xt::SysexCommand::EmuLEDs: + if(m_frontPanel) + m_frontPanel->processSysex(_msg); + return true; + default: + break; + } + } - applyPatchParameters(_params, 0); -} + LOG("Got sysex of size " << _msg.size()); -bool Controller::parseSysexMessage(const pluginLib::SysEx& _msg, synthLib::MidiEventSource) -{ - if(_msg.size() >= 5) - { - switch (const auto cmd = static_cast<xt::SysexCommand>(_msg[4])) - { - case xt::SysexCommand::EmuRotaries: - case xt::SysexCommand::EmuButtons: - case xt::SysexCommand::EmuLCD: - case xt::SysexCommand::EmuLEDs: - if(m_frontPanel) - m_frontPanel->processSysex(_msg); - return true; - default: - break; - } - } - - LOG("Got sysex of size " << _msg.size()); - - std::string name; - pluginLib::MidiPacket::Data data; - pluginLib::MidiPacket::ParamValues parameterValues; - - if(!pluginLib::Controller::parseMidiPacket(name, data, parameterValues, _msg)) - return false; + std::string name; + pluginLib::MidiPacket::Data data; + pluginLib::MidiPacket::ParamValues parameterValues; + + if(!pluginLib::Controller::parseMidiPacket(name, data, parameterValues, _msg)) + return false; + + if(name == midiPacketName(SingleDump)) + { + parseSingle(_msg, data, parameterValues); + } + else if (name == midiPacketName(MultiDump)) + { + parseMulti(_msg, data, parameterValues); + } + else if(name == midiPacketName(GlobalDump)) + { + parseGlobal(_msg, data, parameterValues); + } + else if(name == midiPacketName(ModeDump)) + { + const auto lastPlayMode = isMultiMode(); + memcpy(m_modeData.data(), &_msg[xt::IdxModeParamFirst], sizeof(m_modeData)); + const auto newPlayMode = isMultiMode(); + + if(lastPlayMode != newPlayMode) + onPlayModeChanged(newPlayMode); + else + requestAllPatches(); + } + else if(name == midiPacketName(SingleParameterChange)) + { + const auto page = data[pluginLib::MidiDataType::Page]; + const auto index = data[pluginLib::MidiDataType::ParameterIndex]; + const auto part = data[pluginLib::MidiDataType::Part]; + const auto value = data[pluginLib::MidiDataType::ParameterValue]; + + auto& params = findSynthParam(part, page, index); + + for (auto& param : params) + param->setValueFromSynth(value, pluginLib::Parameter::Origin::Midi); - if(name == midiPacketName(SingleDump)) - { - parseSingle(_msg, data, parameterValues); - } - else if (name == midiPacketName(MultiDump)) - { - parseMulti(_msg, data, parameterValues); - } - else if(name == midiPacketName(GlobalDump)) - { - parseGlobal(_msg, data, parameterValues); - } - else if(name == midiPacketName(ModeDump)) - { - const auto lastPlayMode = isMultiMode(); - memcpy(m_modeData.data(), &_msg[xt::IdxModeParamFirst], sizeof(m_modeData)); - const auto newPlayMode = isMultiMode(); - - if(lastPlayMode != newPlayMode) - onPlayModeChanged(newPlayMode); + LOG("Single parameter " << static_cast<int>(index) << ", page " << static_cast<int>(page) << " for part " << static_cast<int>(part) << " changed to value " << static_cast<int>(value)); + } + else if(name == midiPacketName(GlobalParameterChange)) + { + const auto index = (static_cast<uint32_t>(data[pluginLib::MidiDataType::Page]) << 7) + static_cast<uint32_t>(data[pluginLib::MidiDataType::ParameterIndex]); + const auto value = data[pluginLib::MidiDataType::ParameterValue]; + + if(m_globalData[index] != value) + { + LOG("Global parameter " << index << " changed to value " << static_cast<int>(value)); + m_globalData[index] = value; + } + } + else if(name == midiPacketName(WaveDump)) + { + if(m_waveEditor) + m_waveEditor->onReceiveWave(data, _msg); + } + else if(name == midiPacketName(TableDump)) + { + if(m_waveEditor) + m_waveEditor->onReceiveTable(data, _msg); + } else - requestAllPatches(); - } - else if(name == midiPacketName(SingleParameterChange)) - { - const auto page = data[pluginLib::MidiDataType::Page]; - const auto index = data[pluginLib::MidiDataType::ParameterIndex]; - const auto part = data[pluginLib::MidiDataType::Part]; - const auto value = data[pluginLib::MidiDataType::ParameterValue]; - - auto& params = findSynthParam(part, page, index); - - for (auto& param : params) - param->setValueFromSynth(value, pluginLib::Parameter::Origin::Midi); - - LOG("Single parameter " << static_cast<int>(index) << ", page " << static_cast<int>(page) << " for part " << static_cast<int>(part) << " changed to value " << static_cast<int>(value)); - } - else if(name == midiPacketName(GlobalParameterChange)) - { - const auto index = (static_cast<uint32_t>(data[pluginLib::MidiDataType::Page]) << 7) + static_cast<uint32_t>(data[pluginLib::MidiDataType::ParameterIndex]); - const auto value = data[pluginLib::MidiDataType::ParameterValue]; - - if(m_globalData[index] != value) { - LOG("Global parameter " << index << " changed to value " << static_cast<int>(value)); - m_globalData[index] = value; + LOG("Received unknown sysex of size " << _msg.size()); + return false; } - } - else if(name == midiPacketName(WaveDump)) + return true; + } + + bool Controller::parseControllerMessage(const synthLib::SMidiEvent&) { - if(m_waveEditor) - m_waveEditor->onReceiveWave(data, _msg); + // TODO + return false; } - else if(name == midiPacketName(TableDump)) + + bool Controller::parseMidiPacket(MidiPacketType _type, pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _params, const pluginLib::SysEx& _sysex) const { - if(m_waveEditor) - m_waveEditor->onReceiveTable(data, _msg); + const auto* p = getMidiPacket(g_midiPacketNames[_type]); + assert(p && "midi packet not found"); + return pluginLib::Controller::parseMidiPacket(*p, _data, _params, _sysex); } - else - { - LOG("Received unknown sysex of size " << _msg.size()); - return false; - } - return true; -} -bool Controller::parseControllerMessage(const synthLib::SMidiEvent&) -{ - // TODO - return false; -} + bool Controller::sendSysEx(MidiPacketType _type) const + { + std::map<pluginLib::MidiDataType, uint8_t> params; + return sendSysEx(_type, params); + } -bool Controller::parseMidiPacket(MidiPacketType _type, pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _params, const pluginLib::SysEx& _sysex) const -{ - const auto* p = getMidiPacket(g_midiPacketNames[_type]); - assert(p && "midi packet not found"); - return pluginLib::Controller::parseMidiPacket(*p, _data, _params, _sysex); -} + bool Controller::sendSysEx(const MidiPacketType _type, std::map<pluginLib::MidiDataType, uint8_t>& _params) const + { + _params.insert(std::make_pair(pluginLib::MidiDataType::DeviceId, m_deviceId)); + return pluginLib::Controller::sendSysEx(midiPacketName(_type), _params); + } -bool Controller::sendSysEx(MidiPacketType _type) const -{ - std::map<pluginLib::MidiDataType, uint8_t> params; - return sendSysEx(_type, params); -} + bool Controller::isMultiMode() const + { + return m_modeData.front() != 0; + } -bool Controller::sendSysEx(const MidiPacketType _type, std::map<pluginLib::MidiDataType, uint8_t>& _params) const -{ - _params.insert(std::make_pair(pluginLib::MidiDataType::DeviceId, m_deviceId)); - return pluginLib::Controller::sendSysEx(midiPacketName(_type), _params); -} + void Controller::setPlayMode(const bool _multiMode) + { + if(isMultiMode() == _multiMode) + return; -bool Controller::isMultiMode() const -{ - return m_modeData.front() != 0; -} + m_modeData[0] = _multiMode ? 1 : 0; -void Controller::setPlayMode(const bool _multiMode) -{ - if(isMultiMode() == _multiMode) - return; + sendModeDump(); - m_modeData[0] = _multiMode ? 1 : 0; + onPlayModeChanged(_multiMode); + } - sendModeDump(); + void Controller::selectNextPreset() + { + selectPreset(+1); + } - onPlayModeChanged(_multiMode); -} + void Controller::selectPrevPreset() + { + selectPreset(-1); + } -void Controller::selectNextPreset() -{ - selectPreset(+1); -} + std::vector<uint8_t> Controller::createSingleDump(const xt::LocationH _buffer, const uint8_t _location, const uint8_t _part) const + { + pluginLib::MidiPacket::Data data; -void Controller::selectPrevPreset() -{ - selectPreset(-1); -} + data.insert(std::make_pair(pluginLib::MidiDataType::DeviceId, m_deviceId)); + data.insert(std::make_pair(pluginLib::MidiDataType::Bank, static_cast<uint8_t>(_buffer))); + data.insert(std::make_pair(pluginLib::MidiDataType::Program, _location)); -std::vector<uint8_t> Controller::createSingleDump(const xt::LocationH _buffer, const uint8_t _location, const uint8_t _part) const -{ - pluginLib::MidiPacket::Data data; + std::vector<uint8_t> dst; - data.insert(std::make_pair(pluginLib::MidiDataType::DeviceId, m_deviceId)); - data.insert(std::make_pair(pluginLib::MidiDataType::Bank, static_cast<uint8_t>(_buffer))); - data.insert(std::make_pair(pluginLib::MidiDataType::Program, _location)); + if (!createMidiDataFromPacket(dst, midiPacketName(SingleDump), data, _part)) + return {}; - std::vector<uint8_t> dst; + return dst; + } - if (!createMidiDataFromPacket(dst, midiPacketName(SingleDump), data, _part)) - return {}; + std::vector<uint8_t> Controller::createSingleDump(xt::LocationH _buffer, const uint8_t _location, const pluginLib::MidiPacket::AnyPartParamValues& _values) const + { + pluginLib::MidiPacket::Data data; - return dst; -} + data.insert(std::make_pair(pluginLib::MidiDataType::DeviceId, m_deviceId)); + data.insert(std::make_pair(pluginLib::MidiDataType::Bank, static_cast<uint8_t>(_buffer))); + data.insert(std::make_pair(pluginLib::MidiDataType::Program, _location)); -std::vector<uint8_t> Controller::createSingleDump(xt::LocationH _buffer, const uint8_t _location, const pluginLib::MidiPacket::AnyPartParamValues& _values) const -{ - pluginLib::MidiPacket::Data data; + std::vector<uint8_t> dst; - data.insert(std::make_pair(pluginLib::MidiDataType::DeviceId, m_deviceId)); - data.insert(std::make_pair(pluginLib::MidiDataType::Bank, static_cast<uint8_t>(_buffer))); - data.insert(std::make_pair(pluginLib::MidiDataType::Program, _location)); + if (!createMidiDataFromPacket(dst, midiPacketName(SingleDump), data, _values)) + return {}; - std::vector<uint8_t> dst; + return dst; + } - if (!createMidiDataFromPacket(dst, midiPacketName(SingleDump), data, _values)) - return {}; + bool Controller::parseSingle(pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _paramValues, const std::vector<uint8_t>& _sysex) const + { + return parseMidiPacket(SingleDump, _data, _paramValues, _sysex); + } - return dst; -} + bool Controller::setString(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, size_t _len, const std::string& _value) const + { + for(uint32_t i=0; i<_len && i <_value.size(); ++i) + { + char paramName[64]; + (void)snprintf(paramName, sizeof(paramName), "%s%02u", _prefix.c_str(), i); -bool Controller::parseSingle(pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _paramValues, const std::vector<uint8_t>& _sysex) const -{ - return parseMidiPacket(SingleDump, _data, _paramValues, _sysex); -} + const auto idx = getParameterIndexByName(paramName); + if(idx == InvalidParameterIndex) + break; -bool Controller::setString(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, size_t _len, const std::string& _value) const -{ - for(uint32_t i=0; i<_len && i <_value.size(); ++i) - { - char paramName[64]; - (void)snprintf(paramName, sizeof(paramName), "%s%02u", _prefix.c_str(), i); - - const auto idx = getParameterIndexByName(paramName); - if(idx == InvalidParameterIndex) - break; - - _values[idx] = static_cast<uint8_t>(_value[i]); - } - return true; -} + _values[idx] = static_cast<uint8_t>(_value[i]); + } + return true; + } -void Controller::setFrontPanel(xtJucePlugin::FrontPanel* _frontPanel) -{ - m_frontPanel = _frontPanel; -} + void Controller::setFrontPanel(xtJucePlugin::FrontPanel* _frontPanel) + { + m_frontPanel = _frontPanel; + } -void Controller::setWaveEditor(xtJucePlugin::WaveEditor* _waveEditor) -{ - m_waveEditor = _waveEditor; -} + void Controller::setWaveEditor(xtJucePlugin::WaveEditor* _waveEditor) + { + m_waveEditor = _waveEditor; + } -void Controller::selectPreset(const int _offset) -{ - auto& current = isMultiMode() ? m_currentSingles[getCurrentPart()] : m_currentSingle; - - int index = static_cast<int>(current) + _offset; - - if (index < 0) - index += 300; - - if (index >= 300) - index -= 300; - - current = static_cast<uint32_t>(index); - - const int single = index % 100; - const int bank = index / 100; - - if (isMultiMode()) - { - // TODO: modify multi - } - else - { - sendMidiEvent(synthLib::M_CONTROLCHANGE, synthLib::MC_BANKSELECTMSB, m_deviceId); - sendMidiEvent(synthLib::M_CONTROLCHANGE, synthLib::MC_BANKSELECTLSB, static_cast<uint8_t>(xt::LocationH::SingleBankA) + bank); - sendMidiEvent(synthLib::M_PROGRAMCHANGE, static_cast<uint8_t>(single), 0); -/* - sendGlobalParameterChange(xt::GlobalParameter::InstrumentABankNumber, static_cast<uint8_t>(bank)); - sendGlobalParameterChange(xt::GlobalParameter::InstrumentASingleNumber, static_cast<uint8_t>(single)); -*/ } -} + void Controller::selectPreset(const int _offset) + { + auto& current = isMultiMode() ? m_currentSingles[getCurrentPart()] : m_currentSingle; -void Controller::sendParameterChange(const pluginLib::Parameter& _parameter, const pluginLib::ParamValue _value) -{ - const auto &desc = _parameter.getDescription(); + int index = static_cast<int>(current) + _offset; - std::map<pluginLib::MidiDataType, uint8_t> data; + if (index < 0) + index += 300; - switch (desc.page) - { - case g_pageGlobal: - { - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, _parameter.getDescription().index & 0x7f)); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, _value)); + if (index >= 300) + index -= 300; - sendSysEx(GlobalParameterChange, data); - } - return; - case g_pageMulti: - case g_pageMultiInst0: - case g_pageMultiInst1: - case g_pageMultiInst2: - case g_pageMultiInst3: - case g_pageMultiInst4: - case g_pageMultiInst5: - case g_pageMultiInst6: - case g_pageMultiInst7: - { - uint8_t v; + current = static_cast<uint32_t>(index); - if (!combineParameterChange(v, g_midiPacketNames[MultiDump], _parameter, _value)) - return; + const int single = index % 100; + const int bank = index / 100; - uint8_t page; + if (isMultiMode()) + { + // TODO: modify multi + } + else + { + sendMidiEvent(synthLib::M_CONTROLCHANGE, synthLib::MC_BANKSELECTMSB, m_deviceId); + sendMidiEvent(synthLib::M_CONTROLCHANGE, synthLib::MC_BANKSELECTLSB, static_cast<uint8_t>(xt::LocationH::SingleBankA) + bank); + sendMidiEvent(synthLib::M_PROGRAMCHANGE, static_cast<uint8_t>(single), 0); + /* + sendGlobalParameterChange(xt::GlobalParameter::InstrumentABankNumber, static_cast<uint8_t>(bank)); + sendGlobalParameterChange(xt::GlobalParameter::InstrumentASingleNumber, static_cast<uint8_t>(single)); + */ } + } - if(desc.page > g_pageMulti) - page = desc.page - g_pageMultiInst0; - else - page = static_cast<uint8_t>(xt::LocationH::MultiDumpMultiEditBuffer); + void Controller::sendParameterChange(const pluginLib::Parameter& _parameter, const pluginLib::ParamValue _value) + { + const auto &desc = _parameter.getDescription(); - data.insert(std::make_pair(pluginLib::MidiDataType::Part, _parameter.getPart())); - data.insert(std::make_pair(pluginLib::MidiDataType::Page, page)); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, desc.index)); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, v)); + std::map<pluginLib::MidiDataType, uint8_t> data; - sendSysEx(MultiParameterChange, data); - } - return; - case g_pageSoftKnobs: - break; - case g_pageControllers: - break; - default: + switch (desc.page) { - uint8_t v; - if (!combineParameterChange(v, g_midiPacketNames[SingleDump], _parameter, _value)) - return; - - data.insert(std::make_pair(pluginLib::MidiDataType::Part, _parameter.getPart())); - data.insert(std::make_pair(pluginLib::MidiDataType::Page, desc.page)); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, desc.index)); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, v)); - - sendSysEx(SingleParameterChange, data); + case g_pageGlobal: + { + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, _parameter.getDescription().index & 0x7f)); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, _value)); + + sendSysEx(GlobalParameterChange, data); + } + return; + case g_pageMulti: + case g_pageMultiInst0: + case g_pageMultiInst1: + case g_pageMultiInst2: + case g_pageMultiInst3: + case g_pageMultiInst4: + case g_pageMultiInst5: + case g_pageMultiInst6: + case g_pageMultiInst7: + { + uint8_t v; + + if (!combineParameterChange(v, g_midiPacketNames[MultiDump], _parameter, _value)) + return; + + uint8_t page; + + if(desc.page > g_pageMulti) + page = desc.page - g_pageMultiInst0; + else + page = static_cast<uint8_t>(xt::LocationH::MultiDumpMultiEditBuffer); + + data.insert(std::make_pair(pluginLib::MidiDataType::Part, _parameter.getPart())); + data.insert(std::make_pair(pluginLib::MidiDataType::Page, page)); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, desc.index)); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, v)); + + sendSysEx(MultiParameterChange, data); + } + return; + case g_pageSoftKnobs: + break; + case g_pageControllers: + break; + default: + { + uint8_t v; + if (!combineParameterChange(v, g_midiPacketNames[SingleDump], _parameter, _value)) + return; + + data.insert(std::make_pair(pluginLib::MidiDataType::Part, _parameter.getPart())); + data.insert(std::make_pair(pluginLib::MidiDataType::Page, desc.page)); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, desc.index)); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, v)); + + sendSysEx(SingleParameterChange, data); + } + break; } - break; } -} -bool Controller::sendGlobalParameterChange(xt::GlobalParameter _param, uint8_t _value) -{ - const auto index = static_cast<uint32_t>(_param); - - if(m_globalData[index] == _value) - return true; + bool Controller::sendGlobalParameterChange(xt::GlobalParameter _param, uint8_t _value) + { + const auto index = static_cast<uint32_t>(_param); - std::map<pluginLib::MidiDataType, uint8_t> data; + if(m_globalData[index] == _value) + return true; - data.insert(std::make_pair(pluginLib::MidiDataType::Page, index >> 7 )); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, index & 0x7f )); - data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, _value)); + std::map<pluginLib::MidiDataType, uint8_t> data; - m_globalData[index] = _value; + data.insert(std::make_pair(pluginLib::MidiDataType::Page, index >> 7 )); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterIndex, index & 0x7f )); + data.insert(std::make_pair(pluginLib::MidiDataType::ParameterValue, _value)); - return sendSysEx(GlobalParameterChange, data); -} + m_globalData[index] = _value; -bool Controller::sendModeDump() const -{ - std::vector<uint8_t> sysex; - std::map<pluginLib::MidiDataType, uint8_t> data; - data.insert({pluginLib::MidiDataType::DeviceId, m_deviceId}); - if(!createMidiDataFromPacket(sysex, midiPacketName(ModeDump), data, 0)) - return false; - sysex[xt::IdxModeParamFirst] = m_modeData.front(); - pluginLib::Controller::sendSysEx(sysex); - return true; -} - -void Controller::requestSingle(xt::LocationH _buf, uint8_t _location) const -{ - std::map<pluginLib::MidiDataType, uint8_t> params; - params[pluginLib::MidiDataType::Bank] = static_cast<uint8_t>(_buf); - params[pluginLib::MidiDataType::Program] = _location; - sendSysEx(RequestSingle, params); -} - -void Controller::requestMulti(xt::LocationH _buf, uint8_t _location) const -{ - std::map<pluginLib::MidiDataType, uint8_t> params; - params[pluginLib::MidiDataType::Bank] = static_cast<uint8_t>(_buf); - params[pluginLib::MidiDataType::Program] = _location; - sendSysEx(RequestMulti, params); -} + return sendSysEx(GlobalParameterChange, data); + } -bool Controller::requestWave(const uint32_t _number) const -{ - if(!xt::Wave::isValidWaveIndex(_number)) - return false; + bool Controller::sendModeDump() const + { + std::vector<uint8_t> sysex; + std::map<pluginLib::MidiDataType, uint8_t> data; + data.insert({pluginLib::MidiDataType::DeviceId, m_deviceId}); + if(!createMidiDataFromPacket(sysex, midiPacketName(ModeDump), data, 0)) + return false; + sysex[xt::IdxModeParamFirst] = m_modeData.front(); + pluginLib::Controller::sendSysEx(sysex); + return true; + } - std::map<pluginLib::MidiDataType, uint8_t> params; + void Controller::requestSingle(xt::LocationH _buf, uint8_t _location) const + { + std::map<pluginLib::MidiDataType, uint8_t> params; + params[pluginLib::MidiDataType::Bank] = static_cast<uint8_t>(_buf); + params[pluginLib::MidiDataType::Program] = _location; + sendSysEx(RequestSingle, params); + } - params[pluginLib::MidiDataType::Bank] = static_cast<uint8_t>(_number >> 7); - params[pluginLib::MidiDataType::Program] = _number & 0x7f; + void Controller::requestMulti(xt::LocationH _buf, uint8_t _location) const + { + std::map<pluginLib::MidiDataType, uint8_t> params; + params[pluginLib::MidiDataType::Bank] = static_cast<uint8_t>(_buf); + params[pluginLib::MidiDataType::Program] = _location; + sendSysEx(RequestMulti, params); + } - return sendSysEx(RequestWave, params); -} + bool Controller::requestWave(const uint32_t _number) const + { + if(!xt::Wave::isValidWaveIndex(_number)) + return false; -bool Controller::requestTable(const uint32_t _number) const -{ - if(!xt::Wave::isValidTableIndex(_number)) - return false; + std::map<pluginLib::MidiDataType, uint8_t> params; - std::map<pluginLib::MidiDataType, uint8_t> params; + params[pluginLib::MidiDataType::Bank] = static_cast<uint8_t>(_number >> 7); + params[pluginLib::MidiDataType::Program] = _number & 0x7f; - params[pluginLib::MidiDataType::Bank] = static_cast<uint8_t>(_number >> 7); - params[pluginLib::MidiDataType::Program] = _number & 0x7f; + return sendSysEx(RequestWave, params); + } - return sendSysEx(RequestTable, params); -} + bool Controller::requestTable(const uint32_t _number) const + { + if(!xt::Wave::isValidTableIndex(_number)) + return false; -uint8_t Controller::getGlobalParam(xt::GlobalParameter _type) const -{ - return m_globalData[static_cast<uint32_t>(_type)]; -} + std::map<pluginLib::MidiDataType, uint8_t> params; -bool Controller::isDerivedParameter(pluginLib::Parameter& _derived, pluginLib::Parameter& _base) const -{ - if(_derived.getDescription().page >= 100) - return false; + params[pluginLib::MidiDataType::Bank] = static_cast<uint8_t>(_number >> 7); + params[pluginLib::MidiDataType::Program] = _number & 0x7f; - const auto& packetName = g_midiPacketNames[SingleDump]; - const auto* packet = getMidiPacket(packetName); + return sendSysEx(RequestTable, params); + } - if (!packet) + uint8_t Controller::getGlobalParam(xt::GlobalParameter _type) const { - LOG("Failed to find midi packet " << packetName); - return true; + return m_globalData[static_cast<uint32_t>(_type)]; } - - const auto* defA = packet->getDefinitionByParameterName(_derived.getDescription().name); - const auto* defB = packet->getDefinitionByParameterName(_base.getDescription().name); - if (!defA || !defB) - return true; + bool Controller::isDerivedParameter(pluginLib::Parameter& _derived, pluginLib::Parameter& _base) const + { + if(_derived.getDescription().page >= 100) + return false; - return defA->doMasksOverlap(*defB); -} + const auto& packetName = g_midiPacketNames[SingleDump]; + const auto* packet = getMidiPacket(packetName); -void Controller::requestAllPatches() const -{ - if (isMultiMode()) - { - requestMulti(xt::LocationH::MultiDumpMultiEditBuffer, 0); + if (!packet) + { + LOG("Failed to find midi packet " << packetName); + return true; + } + + const auto* defA = packet->getDefinitionByParameterName(_derived.getDescription().name); + const auto* defB = packet->getDefinitionByParameterName(_base.getDescription().name); + + if (!defA || !defB) + return true; - // the other singles 1-7 are requested one after the other after a single has been received - requestSingle(xt::LocationH::SingleEditBufferMultiMode, 0); + return defA->doMasksOverlap(*defB); } - else + + void Controller::requestAllPatches() const { - requestSingle(xt::LocationH::SingleEditBufferSingleMode, 0); + if (isMultiMode()) + { + requestMulti(xt::LocationH::MultiDumpMultiEditBuffer, 0); + + // the other singles 1-7 are requested one after the other after a single has been received + requestSingle(xt::LocationH::SingleEditBufferMultiMode, 0); + } + else + { + requestSingle(xt::LocationH::SingleEditBufferSingleMode, 0); + } } -} +} +\ No newline at end of file diff --git a/source/xtJucePlugin/xtController.h b/source/xtJucePlugin/xtController.h @@ -4,131 +4,131 @@ #include "jucePluginLib/event.h" -namespace xtJucePlugin -{ - class WaveEditor; - class FrontPanel; -} - namespace xt { enum class GlobalParameter; enum class LocationH : uint8_t; } -class AudioPluginAudioProcessor; - -class Controller : public pluginLib::Controller +namespace xtJucePlugin { -public: - enum MidiPacketType - { - RequestSingle, - RequestMulti, - RequestSingleBank, - RequestMultiBank, - RequestGlobal, - RequestMode, - RequestAllSingles, - SingleParameterChange, - MultiParameterChange, - GlobalParameterChange, - SingleDump, - MultiDump, - GlobalDump, - ModeDump, - EmuRequestLcd, - EmuRequestLeds, - EmuSendButton, - EmuSendRotary, - RequestWave, - WaveDump, - RequestTable, - TableDump, - - Count - }; + class WaveEditor; + class FrontPanel; - struct Patch + class AudioPluginAudioProcessor; + + class Controller : public pluginLib::Controller { - std::string name; - std::vector<uint8_t> data; + public: + enum MidiPacketType + { + RequestSingle, + RequestMulti, + RequestSingleBank, + RequestMultiBank, + RequestGlobal, + RequestMode, + RequestAllSingles, + SingleParameterChange, + MultiParameterChange, + GlobalParameterChange, + SingleDump, + MultiDump, + GlobalDump, + ModeDump, + EmuRequestLcd, + EmuRequestLeds, + EmuSendButton, + EmuSendRotary, + RequestWave, + WaveDump, + RequestTable, + TableDump, + + Count + }; + + struct Patch + { + std::string name; + std::vector<uint8_t> data; + }; + + pluginLib::Event<bool> onPlayModeChanged; + pluginLib::Event<uint8_t> onProgramChanged; + + Controller(AudioPluginAudioProcessor &, unsigned char _deviceId = 0); + ~Controller() override; + + bool sendSingle(const std::vector<uint8_t>& _sysex); + bool sendSingle(const std::vector<uint8_t>& _sysex, uint8_t _part); + + bool sendSysEx(MidiPacketType _type) const; + bool sendSysEx(MidiPacketType _type, std::map<pluginLib::MidiDataType, uint8_t>& _params) const; + + bool isMultiMode() const; + void setPlayMode(bool _multiMode); + + void selectNextPreset(); + void selectPrevPreset(); + + std::vector<uint8_t> createSingleDump(xt::LocationH _buffer, uint8_t _location, uint8_t _part) const; + std::vector<uint8_t> createSingleDump(xt::LocationH _buffer, uint8_t _location, const pluginLib::MidiPacket::AnyPartParamValues& _values) const; + bool parseSingle(pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _paramValues, const std::vector<uint8_t>& _sysex) const; + + std::string getSingleName(uint8_t _part) const; + std::string getSingleName(const pluginLib::MidiPacket::ParamValues& _values) const; + std::string getSingleName(const pluginLib::MidiPacket::AnyPartParamValues& _values) const; + std::string getString(const pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, size_t _len) const; + + bool setSingleName(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const; + bool setCategory(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const; + bool setString(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, size_t _len, const std::string& _value) const; + + void setFrontPanel(xtJucePlugin::FrontPanel* _frontPanel); + void setWaveEditor(xtJucePlugin::WaveEditor* _waveEditor); + + bool requestWave(uint32_t _number) const; + bool requestTable(uint32_t _number) const; + + private: + void selectPreset(int _offset); + + static std::string loadParameterDescriptions(); + + void onStateLoaded() override; + uint8_t getPartCount() const override; + + void parseSingle(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params); + void parseMulti(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params) const; + void parseGlobal(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params); + + bool parseMidiPacket(MidiPacketType _type, pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _params, const pluginLib::SysEx& _sysex) const; + + bool parseSysexMessage(const pluginLib::SysEx&, synthLib::MidiEventSource) override; + bool parseControllerMessage(const synthLib::SMidiEvent&) override; + + void sendParameterChange(const pluginLib::Parameter& _parameter, pluginLib::ParamValue _value) override; + bool sendGlobalParameterChange(xt::GlobalParameter _param, uint8_t _value); + bool sendModeDump() const; + void requestSingle(xt::LocationH _buf, uint8_t _location) const; + void requestMulti(xt::LocationH _buf, uint8_t _location) const; + + uint8_t getGlobalParam(xt::GlobalParameter _type) const; + + bool isDerivedParameter(pluginLib::Parameter& _derived, pluginLib::Parameter& _base) const override; + + void requestAllPatches() const; + + const uint8_t m_deviceId; + + Patch m_singleEditBuffer; + std::array<Patch,8> m_singleEditBuffers; + std::array<uint8_t, 39> m_globalData{}; + std::array<uint8_t, 1> m_modeData{}; + std::array<uint32_t, 8> m_currentSingles{0}; + uint32_t m_currentSingle = 0; + xtJucePlugin::FrontPanel* m_frontPanel = nullptr; + xtJucePlugin::WaveEditor* m_waveEditor = nullptr; }; - - pluginLib::Event<bool> onPlayModeChanged; - pluginLib::Event<uint8_t> onProgramChanged; - - Controller(AudioPluginAudioProcessor &, unsigned char _deviceId = 0); - ~Controller() override; - - bool sendSingle(const std::vector<uint8_t>& _sysex); - bool sendSingle(const std::vector<uint8_t>& _sysex, uint8_t _part); - - bool sendSysEx(MidiPacketType _type) const; - bool sendSysEx(MidiPacketType _type, std::map<pluginLib::MidiDataType, uint8_t>& _params) const; - - bool isMultiMode() const; - void setPlayMode(bool _multiMode); - - void selectNextPreset(); - void selectPrevPreset(); - - std::vector<uint8_t> createSingleDump(xt::LocationH _buffer, uint8_t _location, uint8_t _part) const; - std::vector<uint8_t> createSingleDump(xt::LocationH _buffer, uint8_t _location, const pluginLib::MidiPacket::AnyPartParamValues& _values) const; - bool parseSingle(pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _paramValues, const std::vector<uint8_t>& _sysex) const; - - std::string getSingleName(uint8_t _part) const; - std::string getSingleName(const pluginLib::MidiPacket::ParamValues& _values) const; - std::string getSingleName(const pluginLib::MidiPacket::AnyPartParamValues& _values) const; - std::string getString(const pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, size_t _len) const; - - bool setSingleName(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const; - bool setCategory(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _value) const; - bool setString(pluginLib::MidiPacket::AnyPartParamValues& _values, const std::string& _prefix, size_t _len, const std::string& _value) const; - - void setFrontPanel(xtJucePlugin::FrontPanel* _frontPanel); - void setWaveEditor(xtJucePlugin::WaveEditor* _waveEditor); - - bool requestWave(uint32_t _number) const; - bool requestTable(uint32_t _number) const; - -private: - void selectPreset(int _offset); - - static std::string loadParameterDescriptions(); - - void onStateLoaded() override; - uint8_t getPartCount() const override; - - void parseSingle(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params); - void parseMulti(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params) const; - void parseGlobal(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _params); - - bool parseMidiPacket(MidiPacketType _type, pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _params, const pluginLib::SysEx& _sysex) const; - - bool parseSysexMessage(const pluginLib::SysEx&, synthLib::MidiEventSource) override; - bool parseControllerMessage(const synthLib::SMidiEvent&) override; - - void sendParameterChange(const pluginLib::Parameter& _parameter, pluginLib::ParamValue _value) override; - bool sendGlobalParameterChange(xt::GlobalParameter _param, uint8_t _value); - bool sendModeDump() const; - void requestSingle(xt::LocationH _buf, uint8_t _location) const; - void requestMulti(xt::LocationH _buf, uint8_t _location) const; - - uint8_t getGlobalParam(xt::GlobalParameter _type) const; - - bool isDerivedParameter(pluginLib::Parameter& _derived, pluginLib::Parameter& _base) const override; - - void requestAllPatches() const; - - const uint8_t m_deviceId; - - Patch m_singleEditBuffer; - std::array<Patch,8> m_singleEditBuffers; - std::array<uint8_t, 39> m_globalData{}; - std::array<uint8_t, 1> m_modeData{}; - std::array<uint32_t, 8> m_currentSingles{0}; - uint32_t m_currentSingle = 0; - xtJucePlugin::FrontPanel* m_frontPanel = nullptr; - xtJucePlugin::WaveEditor* m_waveEditor = nullptr; -}; +} +\ No newline at end of file diff --git a/source/xtJucePlugin/xtEditor.h b/source/xtJucePlugin/xtEditor.h @@ -6,9 +6,6 @@ #include "jucePluginLib/event.h" -class XtLcd; -class Controller; - namespace jucePluginEditorLib { class MidiPorts; @@ -27,6 +24,8 @@ namespace xtJucePlugin class FocusedParameter; class FrontPanel; class PatchManager; + class XtLcd; + class Controller; class Editor final : public jucePluginEditorLib::Editor { diff --git a/source/xtJucePlugin/xtLcd.cpp b/source/xtJucePlugin/xtLcd.cpp @@ -20,77 +20,80 @@ namespace static_assert(std::size(g_defaultTextMulti) == 80 + 1); } -// 40*2 LCD simulation - -XtLcd::XtLcd(Component& _parent, Controller& _controller) : Lcd(_parent, 40, 2), m_controller(_controller) +namespace xtJucePlugin { - postConstruct(); + // 40*2 LCD simulation - m_currentText.fill(' '); -} + XtLcd::XtLcd(Component& _parent, Controller& _controller) : Lcd(_parent, 40, 2), m_controller(_controller) + { + postConstruct(); -XtLcd::~XtLcd() = default; + m_currentText.fill(' '); + } -void XtLcd::refresh() -{ - setText(m_currentText); -} + XtLcd::~XtLcd() = default; -void XtLcd::setText(const std::array<uint8_t, 80>& _text) -{ - m_currentText = _text; + void XtLcd::refresh() + { + setText(m_currentText); + } + + void XtLcd::setText(const std::array<uint8_t, 80>& _text) + { + m_currentText = _text; - std::vector<uint8_t> text{_text.begin(), _text.end()}; + std::vector<uint8_t> text{_text.begin(), _text.end()}; - if(m_controller.isMultiMode()) - text.back() = '1' + m_controller.getCurrentPart(); + if(m_controller.isMultiMode()) + text.back() = '1' + m_controller.getCurrentPart(); - if(!m_paramName.empty() && !m_paramValue.empty()) - { - const auto param = '[' + m_paramName + " = " + m_paramValue + ']'; - if(param.size() <= 40) + if(!m_paramName.empty() && !m_paramValue.empty()) { - memcpy(text.data() + 40 - param.size(), param.c_str(), param.size()); + const auto param = '[' + m_paramName + " = " + m_paramValue + ']'; + if(param.size() <= 40) + { + memcpy(text.data() + 40 - param.size(), param.c_str(), param.size()); + } } - } - Lcd::setText(text); -} + Lcd::setText(text); + } -bool XtLcd::getOverrideText(std::vector<std::vector<uint8_t>>& _lines) -{ - std::string lineA(std::string("Xenia v") + pluginLib::Version::getVersionString()); - std::string lineB = pluginLib::Version::getVersionDateTime(); + bool XtLcd::getOverrideText(std::vector<std::vector<uint8_t>>& _lines) + { + std::string lineA(std::string("Xenia v") + pluginLib::Version::getVersionString()); + std::string lineB = pluginLib::Version::getVersionDateTime(); - constexpr char lineAright[] = "From TUS"; - constexpr char lineBright[] = "with <3"; + constexpr char lineAright[] = "From TUS"; + constexpr char lineBright[] = "with <3"; - while(lineA.size() < 40 - std::size(lineAright) + 1) - lineA.push_back(' '); - lineA += lineAright; + while(lineA.size() < 40 - std::size(lineAright) + 1) + lineA.push_back(' '); + lineA += lineAright; - while(lineB.size() < 40 - std::size(lineBright) + 1) - lineB.push_back(' '); - lineB += lineBright; + while(lineB.size() < 40 - std::size(lineBright) + 1) + lineB.push_back(' '); + lineB += lineBright; - _lines = - { - std::vector<uint8_t>(lineA.begin(), lineA.end()), - std::vector<uint8_t>(lineB.begin(), lineB.end()) - }; + _lines = + { + std::vector<uint8_t>(lineA.begin(), lineA.end()), + std::vector<uint8_t>(lineB.begin(), lineB.end()) + }; - return true; -} + return true; + } -const uint8_t* XtLcd::getCharacterData(const uint8_t _character) const -{ - return hwLib::getCharacterData(_character); -} + const uint8_t* XtLcd::getCharacterData(const uint8_t _character) const + { + return hwLib::getCharacterData(_character); + } -void XtLcd::setCurrentParameter(const std::string& _name, const std::string& _value) -{ - m_paramName = _name; - m_paramValue = _value; + void XtLcd::setCurrentParameter(const std::string& _name, const std::string& _value) + { + m_paramName = _name; + m_paramValue = _value; - setText(m_currentText); -} + setText(m_currentText); + } +} +\ No newline at end of file diff --git a/source/xtJucePlugin/xtLcd.h b/source/xtJucePlugin/xtLcd.h @@ -7,25 +7,28 @@ #include "jucePluginEditorLib/lcd.h" -class Controller; - -class XtLcd final : public jucePluginEditorLib::Lcd +namespace xtJucePlugin { -public: - explicit XtLcd(Component& _parent, Controller& _controller); - ~XtLcd() override; + class Controller; + + class XtLcd final : public jucePluginEditorLib::Lcd + { + public: + explicit XtLcd(Component& _parent, Controller& _controller); + ~XtLcd() override; - void refresh(); - void setText(const std::array<uint8_t, 80> &_text); + void refresh(); + void setText(const std::array<uint8_t, 80> &_text); - bool getOverrideText(std::vector<std::vector<uint8_t>>& _lines) override; - const uint8_t* getCharacterData(uint8_t _character) const override; + bool getOverrideText(std::vector<std::vector<uint8_t>>& _lines) override; + const uint8_t* getCharacterData(uint8_t _character) const override; - void setCurrentParameter(const std::string& _name, const std::string& _value); + void setCurrentParameter(const std::string& _name, const std::string& _value); -private: - std::array<uint8_t, 80> m_currentText; - Controller& m_controller; - std::string m_paramName; - std::string m_paramValue; -}; + private: + std::array<uint8_t, 80> m_currentText; + Controller& m_controller; + std::string m_paramName; + std::string m_paramValue; + }; +} +\ No newline at end of file diff --git a/source/xtJucePlugin/xtPatchManager.h b/source/xtJucePlugin/xtPatchManager.h @@ -2,11 +2,10 @@ #include "jucePluginEditorLib/patchmanager/patchmanager.h" -class Controller; - namespace xtJucePlugin { class Editor; + class Controller; class PatchManager : public jucePluginEditorLib::patchManager::PatchManager {