Fixes #6401: Reload Lv2 plugin on SR change

This also includes banning blop's wavedata plugins, because they crash
on reloading. Reference: https://gitlab.com/drobilla/blop-lv2/-/issues/3
This commit is contained in:
Johannes Lorenz
2022-06-04 23:11:04 +02:00
committed by Johannes Lorenz
parent 7649f5ed24
commit f48dd0fb1f
13 changed files with 168 additions and 41 deletions

View File

@@ -54,30 +54,7 @@ Lv2ControlBase::Lv2ControlBase(Model* that, const QString &uri) :
{
if (m_plugin)
{
int channelsLeft = DEFAULT_CHANNELS; // LMMS plugins are stereo
while (channelsLeft > 0)
{
std::unique_ptr<Lv2Proc> newOne = std::make_unique<Lv2Proc>(m_plugin, that);
if (newOne->isValid())
{
channelsLeft -= std::max(
1 + static_cast<bool>(newOne->inPorts().m_right),
1 + static_cast<bool>(newOne->outPorts().m_right));
Q_ASSERT(channelsLeft >= 0);
m_procs.push_back(std::move(newOne));
}
else
{
qCritical() << "Failed instantiating LV2 processor";
m_valid = false;
channelsLeft = 0;
}
}
if (m_valid)
{
m_channelsPerProc = DEFAULT_CHANNELS / m_procs.size();
linkAllModels();
}
init(that);
}
else
{
@@ -94,6 +71,53 @@ Lv2ControlBase::~Lv2ControlBase() = default;
void Lv2ControlBase::init(Model* meAsModel)
{
int channelsLeft = DEFAULT_CHANNELS; // LMMS plugins are stereo
while (channelsLeft > 0)
{
std::unique_ptr<Lv2Proc> newOne = std::make_unique<Lv2Proc>(m_plugin, meAsModel);
if (newOne->isValid())
{
channelsLeft -= std::max(
1 + static_cast<bool>(newOne->inPorts().m_right),
1 + static_cast<bool>(newOne->outPorts().m_right));
Q_ASSERT(channelsLeft >= 0);
m_procs.push_back(std::move(newOne));
}
else
{
qCritical() << "Failed instantiating LV2 processor";
m_valid = false;
channelsLeft = 0;
}
}
if (m_valid)
{
m_channelsPerProc = DEFAULT_CHANNELS / m_procs.size();
linkAllModels();
}
}
void Lv2ControlBase::shutdown()
{
// currently nothing to do here
}
void Lv2ControlBase::reload()
{
for (const auto& c : m_procs) { c->reload(); }
}
LinkedModelGroup *Lv2ControlBase::getGroup(std::size_t idx)
{
return (m_procs.size() > idx) ? m_procs[idx].get() : nullptr;
@@ -183,14 +207,6 @@ void Lv2ControlBase::loadFile(const QString &file)
void Lv2ControlBase::reloadPlugin()
{
// TODO
}
std::size_t Lv2ControlBase::controlCount() const {
std::size_t res = 0;
for (const auto& c : m_procs) { res += c->controlCount(); }

View File

@@ -105,6 +105,14 @@ void *&Lv2Features::operator[](const char *featName)
}
void Lv2Features::clear()
{
m_featureByUri.clear();
}
} // namespace lmms
#endif // LMMS_HAVE_LV2

View File

@@ -60,6 +60,12 @@ const std::set<const char*, Lv2Manager::CmpStr> Lv2Manager::pluginBlacklist =
"http://calf.sourceforge.net/plugins/TransientDesigner",
"http://calf.sourceforge.net/plugins/Vinyl",
// https://gitlab.com/drobilla/blop-lv2/-/issues/3
"http://drobilla.net/plugins/blop/pulse",
"http://drobilla.net/plugins/blop/sawtooth",
"http://drobilla.net/plugins/blop/square",
"http://drobilla.net/plugins/blop/triangle",
// Visualization, meters, and scopes etc., won't work until we have gui support
"http://distrho.sf.net/plugins/ProM",
"http://distrho.sf.net/plugins/glBars",

View File

@@ -31,6 +31,7 @@
#include <lv2/lv2plug.in/ns/ext/atom/atom.h>
#include <lv2/lv2plug.in/ns/ext/resize-port/resize-port.h>
#include <QDebug>
#include <QDomDocument>
#include <QtGlobal>
#include "AudioEngine.h"
@@ -175,6 +176,26 @@ Lv2Proc::~Lv2Proc() { shutdownPlugin(); }
void Lv2Proc::reload()
{
// save controls, which we want to keep
QDomDocument doc;
QDomElement controls = doc.createElement("controls");
saveValues(doc, controls);
// backup construction variables
const LilvPlugin* plugin = m_plugin;
Model* parent = Model::parentModel();
// destroy everything using RAII ...
this->~Lv2Proc();
// ... and reuse it ("placement new")
new (this) Lv2Proc(plugin, parent);
// reload the controls
loadValues(controls);
}
void Lv2Proc::dumpPorts()
{
std::size_t num = 0;
@@ -424,7 +445,10 @@ void Lv2Proc::shutdownPlugin()
lilv_instance_deactivate(m_instance);
lilv_instance_free(m_instance);
m_instance = nullptr;
m_features.clear();
}
m_valid = true;
}