13
0

LV2: fix port/nth-parameter confusion

various LV2 callbacks from plugin DSP/GUI use raw port_index,
not nth_parameter. This lead to incorrectly queued updates
(_values_last_sent_to_ui) and since 7dac8994f6 to
potential crashes (invalid _controllables[idx]).
This commit is contained in:
Robin Gareus 2024-08-25 15:27:04 +02:00
parent eac3283b49
commit 190cd657b9
Signed by: rgareus
GPG Key ID: A090BCE02CF57F04
2 changed files with 28 additions and 40 deletions

View File

@ -70,7 +70,6 @@ LV2PluginUI::write_from_ui(void* controller,
std::shared_ptr<AutomationControl> ac = me->_controllables[port_index];
if (ac) {
me->_updates.insert (port_index);
ac->set_value(*(const float*)buffer, Controllable::NoGroup);
@ -239,10 +238,8 @@ LV2PluginUI::queue_port_update()
{
const uint32_t num_ports = _lv2->num_ports();
for (uint32_t i = 0; i < num_ports; ++i) {
bool ok;
uint32_t port = _lv2->nth_parameter(i, ok);
if (ok && _lv2->parameter_is_input (i)) {
_updates.insert (port);
if (_lv2->parameter_is_control (i) && _lv2->parameter_is_input(i)) {
_updates.insert (i);
}
}
}
@ -274,9 +271,7 @@ LV2PluginUI::output_update()
/* output ports (values set by DSP) need propagating to GUI */
uint32_t nports = _output_ports.size();
for (uint32_t i = 0; i < nports; ++i) {
uint32_t index = _output_ports[i];
for (auto const& index: _output_ports) {
float val = _pib->control_output (index)->get_parameter ();
if (val != _values_last_sent_to_ui[index]) {
@ -288,14 +283,14 @@ LV2PluginUI::output_update()
}
/* Input ports marked for update because the control value changed
since the last redisplay.
*/
* since the last redisplay.
*/
for (Updates::iterator i = _updates.begin(); i != _updates.end(); ++i) {
float val = _controllables[*i]->get_value ();
for (auto const& i : _updates) {
float val = _controllables[i]->get_value ();
/* push current value to the GUI */
suil_instance_port_event ((SuilInstance*)_inst, (*i), 4, 0, &val);
_values_last_sent_to_ui[(*i)] = val;
suil_instance_port_event ((SuilInstance*)_inst, i, 4, 0, &val);
_values_last_sent_to_ui[i] = val;
}
_updates.clear ();
@ -436,15 +431,6 @@ LV2PluginUI::lv2ui_instantiate(const std::string& title)
#define GET_WIDGET(inst) suil_instance_get_widget((SuilInstance*)inst);
const uint32_t num_ports = _lv2->num_ports();
for (uint32_t i = 0; i < num_ports; ++i) {
if (_lv2->parameter_is_output(i)
&& _lv2->parameter_is_control(i)
&& is_update_wanted(i)) {
_output_ports.push_back(i);
}
}
_external_ui_ptr = NULL;
if (!is_external_ui) {
GtkWidget* c_widget = (GtkWidget*)GET_WIDGET(_inst);
@ -465,28 +451,30 @@ LV2PluginUI::lv2ui_instantiate(const std::string& title)
_external_ui_ptr = (struct lv2_external_ui*)GET_WIDGET(_inst);
}
const uint32_t num_ports = _lv2->num_ports();
_values_last_sent_to_ui = new float[num_ports];
_controllables.resize(num_ports);
for (uint32_t i = 0; i < num_ports; ++i) {
bool ok;
uint32_t port = _lv2->nth_parameter(i, ok);
if (ok) {
/* Cache initial value of the parameter, regardless of
whether it is input or output
*/
if (!_lv2->parameter_is_control (i)) {
continue;
}
_values_last_sent_to_ui[port] = _lv2->get_parameter(port);
_controllables[port] = std::dynamic_pointer_cast<ARDOUR::AutomationControl> (
_pib->control(Evoral::Parameter(PluginAutomation, 0, port)));
/* Cache initial value of the parameter, regardless of whether it is input or output */
if (_lv2->parameter_is_control(port) && _lv2->parameter_is_input(port)) {
if (_controllables[port]) {
_controllables[port]->Changed.connect (control_connections, invalidator (*this), boost::bind (&LV2PluginUI::control_changed, this, port), gui_context());
/* queue for first update ("push") to GUI */
_updates.insert (port);
}
}
_values_last_sent_to_ui[i] = _lv2->get_parameter(i);
_controllables[i] = std::dynamic_pointer_cast<ARDOUR::AutomationControl> (_pib->control(Evoral::Parameter(PluginAutomation, 0, i)));
if (_lv2->parameter_is_input(i)) {
assert (_controllables[i]);
_controllables[i]->Changed.connect (control_connections, invalidator (*this), boost::bind (&LV2PluginUI::control_changed, this, i), gui_context());
/* queue for first update ("push") to GUI */
_updates.insert (i);
}
if (_lv2->parameter_is_output(i) && is_update_wanted(i)) {
_output_ports.push_back (i);
}
}

View File

@ -80,7 +80,7 @@ private:
std::shared_ptr<ARDOUR::PlugInsertBase> _pib;
std::shared_ptr<ARDOUR::LV2Plugin> _lv2;
std::vector<int> _output_ports;
std::vector<uint32_t> _output_ports;
sigc::connection _screen_update_connection;
sigc::connection _message_update_connection;
Gtk::Widget* _gui_widget;