commit 5e2897af88a390cf418672341e01a1a37c81080b
parent a8b474be0f622002672680b4979dd13a6e0db0f1
Author: dsp56300 <dsp56300@users.noreply.github.com>
Date: Sat, 18 May 2024 16:43:59 +0200
[Osirus][OsTIrus][Fix] Editor didn't update knobs if parameters are modified via MIDI control changes by using the physical midi input port
Diffstat:
10 files changed, 161 insertions(+), 127 deletions(-)
diff --git a/source/jucePluginLib/controller.cpp b/source/jucePluginLib/controller.cpp
@@ -431,6 +431,13 @@ namespace pluginLib
return false;
}
+ bool Controller::parseMidiMessage(const synthLib::SMidiEvent& _e)
+ {
+ if(_e.sysex.empty())
+ return parseControllerMessage(_e);
+ return parseSysexMessage(_e.sysex, _e.source);
+ }
+
void Controller::addPluginMidiOut(const std::vector<synthLib::SMidiEvent>& _events)
{
const std::lock_guard l(m_pluginMidiOutLock);
diff --git a/source/jucePluginLib/controller.h b/source/jucePluginLib/controller.h
@@ -55,7 +55,11 @@ namespace pluginLib
uint8_t getCurrentPart() const { return m_currentPart; }
void setCurrentPart(const uint8_t _part) { m_currentPart = _part; }
- virtual void parseSysexMessage(const SysEx&) = 0;
+ virtual bool parseSysexMessage(const SysEx&, synthLib::MidiEventSource) = 0;
+ virtual bool parseControllerMessage(const synthLib::SMidiEvent&) = 0;
+
+ virtual bool parseMidiMessage(const synthLib::SMidiEvent& _e);
+
virtual void onStateLoaded() = 0;
// this is called by the plug-in on audio thread!
diff --git a/source/jucePluginLib/processor.cpp b/source/jucePluginLib/processor.cpp
@@ -79,6 +79,8 @@ namespace pluginLib
void Processor::handleIncomingMidiMessage(juce::MidiInput *source, const juce::MidiMessage &message)
{
+ synthLib::SMidiEvent sm(synthLib::MidiEventSource::PhysicalInput);
+
const auto* raw = message.getSysExData();
if (raw)
{
@@ -90,10 +92,9 @@ namespace pluginLib
syx.push_back(raw[i]);
}
syx.push_back(0xf7);
- synthLib::SMidiEvent sm(synthLib::MidiEventSource::PhysicalInput);
- sm.sysex = syx;
- getController().parseSysexMessage(syx);
+ sm.sysex = std::move(syx);
+ getController().parseMidiMessage(sm);
addMidiEvent(sm);
if (m_midiOutput)
@@ -110,8 +111,6 @@ namespace pluginLib
}
else
{
- synthLib::SMidiEvent sm(synthLib::MidiEventSource::PhysicalInput);
-
const auto count = message.getRawDataSize();
const auto* rawData = message.getRawData();
if (count >= 1 && count <= 3)
@@ -128,6 +127,7 @@ namespace pluginLib
sm.sysex = syx;
}
+ getController().parseMidiMessage(sm);
addMidiEvent(sm);
}
}
diff --git a/source/mqJucePlugin/mqController.cpp b/source/mqJucePlugin/mqController.cpp
@@ -121,7 +121,7 @@ void Controller::timerCallback()
for (const auto& e : events)
{
if(!e.sysex.empty())
- parseSysexMessage(e.sysex);
+ parseSysexMessage(e.sysex, e.source);
}
}
@@ -247,7 +247,7 @@ void Controller::parseMulti(const pluginLib::SysEx& _msg, const pluginLib::MidiP
}
}
-void Controller::parseSysexMessage(const pluginLib::SysEx& _msg)
+bool Controller::parseSysexMessage(const pluginLib::SysEx& _msg, synthLib::MidiEventSource _source)
{
if(_msg.size() >= 5)
{
@@ -261,7 +261,7 @@ void Controller::parseSysexMessage(const pluginLib::SysEx& _msg)
case mqLib::SysexCommand::EmuLEDs:
if(m_frontPanel)
m_frontPanel->processSysex(_msg);
- return;
+ return true;
default:
break;
}
@@ -273,60 +273,68 @@ void Controller::parseSysexMessage(const pluginLib::SysEx& _msg)
pluginLib::MidiPacket::Data data;
pluginLib::MidiPacket::ParamValues parameterValues;
- if(pluginLib::Controller::parseMidiPacket(name, data, parameterValues, _msg))
+ if(!pluginLib::Controller::parseMidiPacket(name, data, parameterValues, _msg))
+ return false;
+
+ if(name == midiPacketName(SingleDump))
{
- 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];
+ 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);
+ auto& params = findSynthParam(part, page, index);
- for (auto& param : params)
- param->setValueFromSynth(value, true, pluginLib::Parameter::ChangedBy::ControlChange);
+ for (auto& param : params)
+ param->setValueFromSynth(value, true, pluginLib::Parameter::ChangedBy::ControlChange);
- 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];
+ 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;
+ if(m_globalData[index] != value)
+ {
+ LOG("Global parameter " << index << " changed to value " << static_cast<int>(value));
+ m_globalData[index] = value;
- if (index == static_cast<uint32_t>(mqLib::GlobalParameter::SingleMultiMode))
- requestAllPatches();
- }
- }
- else
- {
- LOG("Received unknown sysex of size " << _msg.size());
- }
+ if (index == static_cast<uint32_t>(mqLib::GlobalParameter::SingleMultiMode))
+ requestAllPatches();
+ }
}
+ else
+ {
+ LOG("Received unknown sysex of size " << _msg.size());
+ return false;
+ }
+ return true;
+}
+
+bool Controller::parseControllerMessage(const synthLib::SMidiEvent&)
+{
+ // TODO
+ return false;
}
bool Controller::parseMidiPacket(MidiPacketType _type, pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _params, const pluginLib::SysEx& _sysex) const
diff --git a/source/mqJucePlugin/mqController.h b/source/mqJucePlugin/mqController.h
@@ -89,9 +89,11 @@ private:
void applyPatchParameters(const pluginLib::MidiPacket::ParamValues& _params, uint8_t _part);
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);
- void parseSysexMessage(const pluginLib::SysEx&) override;
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, uint8_t _value) override;
bool sendGlobalParameterChange(mqLib::GlobalParameter _param, uint8_t _value);
void requestSingle(mqLib::MidiBufferNum _buf, mqLib::MidiSoundLocation _location, uint8_t _locationOffset = 0) const;
diff --git a/source/virusJucePlugin/VirusController.cpp b/source/virusJucePlugin/VirusController.cpp
@@ -87,7 +87,7 @@ namespace Virus
stopTimer();
}
- void Controller::parseSysexMessage(const pluginLib::SysEx& _msg)
+ bool Controller::parseSysexMessage(const pluginLib::SysEx& _msg, synthLib::MidiEventSource)
{
std::string name;
pluginLib::MidiPacket::Data data;
@@ -98,7 +98,7 @@ namespace Virus
const auto deviceId = data[pluginLib::MidiDataType::DeviceId];
if(deviceId != m_deviceId && deviceId != virusLib::OMNI_DEVICE_ID)
- return; // not intended to this device!
+ return false; // not intended to this device!
if(name == midiPacketName(MidiPacketType::SingleDump) || name == midiPacketName(MidiPacketType::SingleDump_C))
parseSingle(_msg, data, parameterValues);
@@ -111,13 +111,20 @@ namespace Virus
LOG("Controller: Begin unhandled SysEx! --");
printMessage(_msg);
LOG("Controller: End unhandled SysEx! --");
+ return false;
}
- return;
+ return true;
}
LOG("Controller: Begin unknown SysEx! --");
printMessage(_msg);
LOG("Controller: End unknown SysEx! --");
+ return false;
+ }
+
+ bool Controller::parseControllerMessage(const synthLib::SMidiEvent& e)
+ {
+ return parseControllerDump(e);
}
juce::Value* Controller::getParamValue(uint8_t ch, uint8_t bank, uint8_t paramIndex)
@@ -534,7 +541,7 @@ namespace Virus
}
}
- void Controller::parseControllerDump(const synthLib::SMidiEvent& m)
+ bool Controller::parseControllerDump(const synthLib::SMidiEvent& m)
{
const uint8_t status = m.a & 0xf0;
const uint8_t part = m.a & 0x0f;
@@ -546,11 +553,13 @@ namespace Virus
else if (status == synthLib::M_POLYPRESSURE)
page = virusLib::PAGE_B;
else
- return;
+ return false;
const auto& params = findSynthParam(part, page, m.b);
for (const auto & p : params)
p->setValueFromSynth(m.c, true, pluginLib::Parameter::ChangedBy::ControlChange);
+
+ return true;
}
void Controller::printMessage(const pluginLib::SysEx &msg)
@@ -663,7 +672,7 @@ namespace Virus
}
else
{
- parseSysexMessage(msg.sysex);
+ parseSysexMessage(msg.sysex, msg.source);
}
}
}
diff --git a/source/virusJucePlugin/VirusController.h b/source/virusJucePlugin/VirusController.h
@@ -126,7 +126,8 @@ namespace Virus
juce::String getCurrentPartPresetName(uint8_t _part) const;
uint32_t getBankCount() const { return static_cast<uint32_t>(m_singles.size()); }
- void parseSysexMessage(const pluginLib::SysEx &) override;
+ bool parseSysexMessage(const pluginLib::SysEx& _msg, synthLib::MidiEventSource _source) override;
+ bool parseControllerMessage(const synthLib::SMidiEvent&) override;
void onStateLoaded() override;
std::function<void(int)> onProgramChange = {};
std::function<void()> onMsgDone = {};
@@ -171,7 +172,7 @@ namespace Virus
void parseMulti(const pluginLib::SysEx& _msg, const pluginLib::MidiPacket::Data& _data, const pluginLib::MidiPacket::ParamValues& _parameterValues);
void parseParamChange(const pluginLib::MidiPacket::Data& _data);
- void parseControllerDump(const synthLib::SMidiEvent&);
+ bool parseControllerDump(const synthLib::SMidiEvent&);
VirusProcessor& m_processor;
virusLib::DeviceModel m_defaultModel;
diff --git a/source/virusLib/microcontroller.cpp b/source/virusLib/microcontroller.cpp
@@ -815,14 +815,6 @@ bool Microcontroller::sendSysex(const std::vector<uint8_t>& _data, std::vector<S
}
}
- // bounce back to UI if not sent by editor
- if(_source != MidiEventSource::Editor)
- {
- SMidiEvent ev(MidiEventSource::Editor); // don't send to output
- ev.sysex = _data;
- _responses.push_back(ev);
- }
-
return send(page, part, param, value);
}
default:
diff --git a/source/xtJucePlugin/xtController.cpp b/source/xtJucePlugin/xtController.cpp
@@ -164,7 +164,7 @@ void Controller::timerCallback()
for (const auto& e : events)
{
if(!e.sysex.empty())
- parseSysexMessage(e.sysex);
+ parseSysexMessage(e.sysex, e.source);
}
}
@@ -309,7 +309,7 @@ void Controller::parseGlobal(const pluginLib::SysEx& _msg, const pluginLib::Midi
applyPatchParameters(_params, 0);
}
-void Controller::parseSysexMessage(const pluginLib::SysEx& _msg)
+bool Controller::parseSysexMessage(const pluginLib::SysEx& _msg, synthLib::MidiEventSource)
{
if(_msg.size() >= 5)
{
@@ -321,7 +321,7 @@ void Controller::parseSysexMessage(const pluginLib::SysEx& _msg)
case xt::SysexCommand::EmuLEDs:
if(m_frontPanel)
m_frontPanel->processSysex(_msg);
- return;
+ return true;
default:
break;
}
@@ -333,61 +333,69 @@ void Controller::parseSysexMessage(const pluginLib::SysEx& _msg)
pluginLib::MidiPacket::Data data;
pluginLib::MidiPacket::ParamValues parameterValues;
- if(pluginLib::Controller::parseMidiPacket(name, data, parameterValues, _msg))
- {
- 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(!pluginLib::Controller::parseMidiPacket(name, data, parameterValues, _msg))
+ return false;
- 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];
+ 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);
+ auto& params = findSynthParam(part, page, index);
- for (auto& param : params)
- param->setValueFromSynth(value, true, pluginLib::Parameter::ChangedBy::ControlChange);
+ for (auto& param : params)
+ param->setValueFromSynth(value, true, pluginLib::Parameter::ChangedBy::ControlChange);
- 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
- {
- LOG("Received unknown sysex of size " << _msg.size());
- }
+ 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
+ {
+ LOG("Received unknown sysex of size " << _msg.size());
+ return false;
+ }
+ return true;
+}
+
+bool Controller::parseControllerMessage(const synthLib::SMidiEvent&)
+{
+ // TODO
+ return false;
}
bool Controller::parseMidiPacket(MidiPacketType _type, pluginLib::MidiPacket::Data& _data, pluginLib::MidiPacket::AnyPartParamValues& _params, const pluginLib::SysEx& _sysex) const
diff --git a/source/xtJucePlugin/xtController.h b/source/xtJucePlugin/xtController.h
@@ -95,9 +95,12 @@ private:
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);
- void parseSysexMessage(const pluginLib::SysEx&) override;
+
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, uint8_t _value) override;
bool sendGlobalParameterChange(xt::GlobalParameter _param, uint8_t _value);
bool sendModeDump() const;