#include "ardour/lv2_plugin.h"
#include "ardour/session.h"
#include "pbd/error.h"
+#include "pbd/stacktrace.h"
+#include "gui_thread.h"
#include "lv2_plugin_ui.h"
#include "timers.h"
}
boost::shared_ptr<AutomationControl> ac = me->_controllables[port_index];
+ /* Cache our local copy of the last value received from the GUI */
+ me->_values[port_index] = *(const float*) buffer;
+ /* Now update the control itself */
if (ac) {
ac->set_value(*(const float*)buffer);
}
}
void
-LV2PluginUI::parameter_changed(uint32_t port_index, float val)
+LV2PluginUI::control_changed (uint32_t port_index)
{
- PlugUIBase::parameter_changed(port_index, val);
-
- if (val != _values[port_index]) {
- parameter_update(port_index, val);
+ /* Must run in GUI thread because we modify _updates with no lock */
+ if (_lv2->get_parameter (port_index) != _values[port_index]) {
+ /* current plugin parameter does not match last value received
+ from GUI, so queue an update to push it to the GUI during
+ our regular timeout.
+ */
+ _updates.insert (port_index);
}
}
-void
-LV2PluginUI::parameter_update(uint32_t port_index, float val)
-{
- if (!_inst) {
- return;
- }
-
- suil_instance_port_event((SuilInstance*)_inst, port_index, 4, 0, &val);
- _values[port_index] = val;
-}
-
bool
LV2PluginUI::start_updating(GdkEventAny*)
{
}
}
- /* FIXME only works with control output ports (which is all we support now anyway) */
- uint32_t nports = _output_ports.size();
- for (uint32_t i = 0; i < nports; ++i) {
- uint32_t index = _output_ports[i];
- parameter_changed(index, _lv2->get_parameter(index));
+ if (_inst) {
+ for (Updates::iterator i = _updates.begin(); i != _updates.end(); ++i) {
+ float val = _lv2->get_parameter (*i);
+ /* push current value to the GUI */
+ suil_instance_port_event ((SuilInstance*)_inst, (*i), 4, 0, &val);
+ }
+ _updates.clear ();
}
-
}
LV2PluginUI::LV2PluginUI(boost::shared_ptr<PluginInsert> pi,
bool ok;
uint32_t port = _lv2->nth_parameter(i, ok);
if (ok) {
- _values[port] = _lv2->get_parameter(port);
_controllables[port] = boost::dynamic_pointer_cast<ARDOUR::AutomationControl> (
insert->control(Evoral::Parameter(PluginAutomation, 0, port)));
- if (_lv2->parameter_is_control(port) && _lv2->parameter_is_input(port)) {
- parameter_update(port, _values[port]);
+ /* FIXME only works with control output ports (which is all we support now anyway) */
+ if (_controllables[port] && _lv2->parameter_is_control(port) && _lv2->parameter_is_input(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);
}
}
}
LV2PluginUI::~LV2PluginUI ()
{
- if (_values) {
- delete[] _values;
- }
+ delete [] _values;
_message_update_connection.disconnect();
_screen_update_connection.disconnect();
plugin->PresetAdded.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::preset_added_or_removed, this), gui_context ());
plugin->PresetRemoved.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::preset_added_or_removed, this), gui_context ());
plugin->PresetLoaded.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::update_preset, this), gui_context ());
- plugin->ParameterChanged.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::parameter_changed, this, _1, _2), gui_context ());
+ plugin->PresetDirty.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::update_preset_modified, this), gui_context ());
insert->AutomationStateChanged.connect (*this, invalidator (*this), boost::bind (&PlugUIBase::automation_state_changed, this), gui_context());
}
}
-void
-PlugUIBase::parameter_changed (uint32_t, float)
-{
- update_preset_modified ();
-}
-
void
PlugUIBase::preset_added_or_removed ()
{