commit 2c76bef819e904dcae061b68d407bdf0de876c4f
parent 37b267ef77bc7253e0c800def35eb60673c02014
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Fri, 2 Aug 2024 01:45:41 +0200
support part select and editing of other parts
Diffstat:
8 files changed, 84 insertions(+), 7 deletions(-)
diff --git a/source/nord/n2x/n2xJucePlugin/n2xController.cpp b/source/nord/n2x/n2xJucePlugin/n2xController.cpp
@@ -41,6 +41,11 @@ namespace n2xJucePlugin
requestDump(n2x::SysexByte::SingleRequestBankEditBuffer, 3);
requestDump(n2x::SysexByte::MultiRequestBankEditBuffer, 0); // performance edit buffer
+
+ m_currentPartChanged.set(onCurrentPartChanged, [this](const uint8_t& _part)
+ {
+ setMultiParameter(n2x::SelectedChannel, _part);
+ });
}
Controller::~Controller() = default;
@@ -128,6 +133,9 @@ namespace n2xJucePlugin
applyPatchParameters(params, 0);
+ const auto part = m_state.getMultiParam(n2x::SelectedChannel, 0);
+ setCurrentPart(part);
+
return true;
}
@@ -182,7 +190,7 @@ namespace n2xJucePlugin
const auto& controllerMap = getParameterDescriptions().getControllerMap();
- const auto& ccs = controllerMap.getControlChanges(synthLib::M_CONTROLCHANGE, _parameter.getParameterIndex());
+ const auto& ccs = controllerMap.getControlChanges(synthLib::M_CONTROLCHANGE, _parameter.getDescription().index);
if(ccs.empty())
{
assert(false && "TODO: implement parameter sending for non-CC params");
@@ -200,8 +208,19 @@ namespace n2xJucePlugin
_value = static_cast<uint8_t>(paramSync->getUnnormalizedValue() | (paramRingMod->getUnnormalizedValue() << 1));
}
- m_state.receive(synthLib::SMidiEvent{synthLib::MidiEventSource::Editor, synthLib::M_CONTROLCHANGE, cc, _value});
- sendMidiEvent(synthLib::M_CONTROLCHANGE, cc, _value);
+ const auto ch = m_state.getPartMidiChannel(_parameter.getPart());
+ const auto ev = synthLib::SMidiEvent{synthLib::MidiEventSource::Editor, static_cast<uint8_t>(synthLib::M_CONTROLCHANGE + ch), cc, _value};
+
+ m_state.receive(ev);
+ sendMidiEvent(ev);
+ }
+
+ void Controller::setMultiParameter(n2x::MultiParam _mp, uint8_t _value)
+ {
+ if(!m_state.changeMultiParameter(_mp, _value))
+ return;
+ const auto& multi = m_state.updateAndGetMulti();
+ pluginLib::Controller::sendSysEx(pluginLib::SysEx{multi.begin(), multi.end()});
}
void Controller::sendMultiParameter(const pluginLib::Parameter& _parameter, const uint8_t _value)
@@ -210,10 +229,7 @@ namespace n2xJucePlugin
const auto mp = static_cast<n2x::MultiParam>(desc.index + (desc.page - g_multiPage) * 128);
- if(!m_state.changeMultiParameter(mp, _value))
- return;
- const auto& multi = m_state.updateAndGetMulti();
- pluginLib::Controller::sendSysEx(pluginLib::SysEx{multi.begin(), multi.end()});
+ setMultiParameter(mp, _value);
}
bool Controller::sendSysEx(MidiPacketType _packet, const std::map<pluginLib::MidiDataType, uint8_t>& _params) const
diff --git a/source/nord/n2x/n2xJucePlugin/n2xController.h b/source/nord/n2x/n2xJucePlugin/n2xController.h
@@ -39,6 +39,7 @@ namespace n2xJucePlugin
bool parseControllerMessage(const synthLib::SMidiEvent&) override;
void sendParameterChange(const pluginLib::Parameter& _parameter, uint8_t _value) override;
+ void setMultiParameter(n2x::MultiParam _mp, uint8_t _value);
void sendMultiParameter(const pluginLib::Parameter& _parameter, uint8_t _value);
bool sendSysEx(MidiPacketType _packet, const std::map<pluginLib::MidiDataType, uint8_t>& _params) const;
@@ -51,5 +52,6 @@ namespace n2xJucePlugin
private:
n2x::State m_state;
+ pluginLib::EventListener<uint8_t> m_currentPartChanged;
};
}
diff --git a/source/nord/n2x/n2xJucePlugin/n2xEditor.cpp b/source/nord/n2x/n2xJucePlugin/n2xEditor.cpp
@@ -70,6 +70,12 @@ namespace n2xJucePlugin
m_arp.reset(new Arp(*this));
m_lcd.reset(new Lcd(*this));
m_parts.reset(new Parts(*this));
+
+ onPartChanged.set(m_controller.onCurrentPartChanged, [this](const uint8_t& _part)
+ {
+ setCurrentPart(_part);
+ m_parameterBinding.setPart(_part);
+ });
}
Editor::~Editor()
diff --git a/source/nord/n2x/n2xJucePlugin/n2xEditor.h b/source/nord/n2x/n2xJucePlugin/n2xEditor.h
@@ -39,6 +39,7 @@ namespace n2xJucePlugin
Controller& getN2xController() const { return m_controller; }
genericUI::Button<juce::DrawableButton>* createJuceComponent(genericUI::Button<juce::DrawableButton>*, genericUI::UiObject& _object, const std::string& _name, juce::DrawableButton::ButtonStyle) override;
+
private:
Controller& m_controller;
pluginLib::ParameterBinding& m_parameterBinding;
@@ -46,5 +47,6 @@ namespace n2xJucePlugin
std::unique_ptr<Arp> m_arp;
std::unique_ptr<Lcd> m_lcd;
std::unique_ptr<Parts> m_parts;
+ pluginLib::EventListener<uint8_t> onPartChanged;
};
}
diff --git a/source/nord/n2x/n2xJucePlugin/n2xPart.cpp b/source/nord/n2x/n2xJucePlugin/n2xPart.cpp
@@ -1,4 +1,6 @@
#include "n2xPart.h"
+
+#include "n2xController.h"
#include "n2xEditor.h"
namespace n2xJucePlugin
@@ -6,4 +8,9 @@ namespace n2xJucePlugin
Part::Part(Editor& _editor, const std::string& _name, const ButtonStyle _buttonStyle) : PartButton(_editor, _name, _buttonStyle), m_editor(_editor)
{
}
+
+ void Part::onClick()
+ {
+ m_editor.getN2xController().setCurrentPart(getPart());
+ }
}
diff --git a/source/nord/n2x/n2xJucePlugin/n2xPart.h b/source/nord/n2x/n2xJucePlugin/n2xPart.h
@@ -11,6 +11,8 @@ namespace n2xJucePlugin
public:
Part(Editor& _editor, const std::string& _name, ButtonStyle _buttonStyle);
+ void onClick() override;
+
private:
Editor& m_editor;
};
diff --git a/source/nord/n2x/n2xJucePlugin/n2xParts.cpp b/source/nord/n2x/n2xJucePlugin/n2xParts.cpp
@@ -1,8 +1,40 @@
#include "n2xParts.h"
+#include "n2xController.h"
+#include "n2xEditor.h"
+
namespace n2xJucePlugin
{
Parts::Parts(Editor& _editor): m_editor(_editor)
{
+ m_parts[0] = _editor.findComponentT<Part>("PerfMidiChannelA");
+ m_parts[1] = _editor.findComponentT<Part>("PerfMidiChannelB");
+ m_parts[2] = _editor.findComponentT<Part>("PerfMidiChannelC");
+ m_parts[3] = _editor.findComponentT<Part>("PerfMidiChannelD");
+
+ for(uint8_t p=0; p<static_cast<uint8_t>(m_parts.size()); ++p)
+ {
+ auto* part = m_parts[p];
+ part->initalize(p);
+ }
+
+ onCurrentPartChanged.set(_editor.getN2xController().onCurrentPartChanged, [this](const uint8_t& _part)
+ {
+ setCurrentPart(_part);
+ });
+
+ setCurrentPart(0);
+ }
+
+ void Parts::setCurrentPart(const uint8_t _part) const
+ {
+ juce::MessageManager::callAsync([this, _part]
+ {
+ for(uint8_t p=0; p<static_cast<uint8_t>(m_parts.size()); ++p)
+ {
+ auto* part = m_parts[p];
+ part->setToggleState(_part == p, juce::dontSendNotification);
+ }
+ });
}
}
diff --git a/source/nord/n2x/n2xJucePlugin/n2xParts.h b/source/nord/n2x/n2xJucePlugin/n2xParts.h
@@ -1,5 +1,9 @@
#pragma once
+#include "n2xPart.h"
+
+#include "jucePluginLib/event.h"
+
namespace n2xJucePlugin
{
class Editor;
@@ -10,6 +14,12 @@ namespace n2xJucePlugin
explicit Parts(Editor& _editor);
private:
+ void setCurrentPart(uint8_t _part) const;
+
Editor& m_editor;
+
+ std::array<Part*,4> m_parts;
+ pluginLib::EventListener<uint8_t> onCurrentPartChanged;
+
};
}