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:
parent
eac3283b49
commit
190cd657b9
@ -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());
|
||||
_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 (port);
|
||||
}
|
||||
_updates.insert (i);
|
||||
}
|
||||
|
||||
if (_lv2->parameter_is_output(i) && is_update_wanted(i)) {
|
||||
_output_ports.push_back (i);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user