mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 15:25:01 +01:00
Catch up with plugin property changes (LV2/JUCE)
When a user changes a value in the Plugin GUI, JUCE informs the DSP behind the host's back, and later informs the host from the DSP (realtime) thread, by sending patch:Set messages from the DSP back to the host/UI. This is really bad practice, particularly since the plugin does no even use LV2 instance access, or LV2 data access features.
This commit is contained in:
parent
e974a861ea
commit
ae6900d8af
8 changed files with 87 additions and 0 deletions
|
|
@ -118,6 +118,7 @@ private:
|
|||
std::string ensure_io_name (std::string) const;
|
||||
void create_parameters ();
|
||||
void parameter_changed_externally (uint32_t, float);
|
||||
void property_changed_externally (uint32_t, Variant);
|
||||
|
||||
void setup ();
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ public:
|
|||
std::shared_ptr<AutomationList> list = std::shared_ptr<AutomationList> ());
|
||||
|
||||
virtual double get_value (void) const;
|
||||
void catch_up_with_external_value (double val);
|
||||
XMLNode& get_state () const;
|
||||
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -276,6 +276,7 @@ private:
|
|||
PluginInsert (const PluginInsert&);
|
||||
|
||||
void parameter_changed_externally (uint32_t, float);
|
||||
void property_changed_externally (uint32_t which, Variant);
|
||||
|
||||
void set_parameter (Evoral::Parameter param, float val, sampleoffset_t);
|
||||
|
||||
|
|
|
|||
|
|
@ -165,6 +165,7 @@ private:
|
|||
bool check_inplace ();
|
||||
void create_parameters ();
|
||||
void parameter_changed_externally (uint32_t, float);
|
||||
void property_changed_externally (uint32_t, Variant);
|
||||
void automation_run (samplepos_t start, pframes_t nframes);
|
||||
bool find_next_event (timepos_t const& start, timepos_t const& end, Evoral::ControlEvent& next_event) const;
|
||||
void start_touch (uint32_t param_id);
|
||||
|
|
|
|||
|
|
@ -256,6 +256,7 @@ IOPlug::setup ()
|
|||
|
||||
_plugin->reconfigure_io (_n_in, aux_in, _n_out);
|
||||
_plugin->ParameterChangedExternally.connect_same_thread (*this, std::bind (&IOPlug::parameter_changed_externally, this, _1, _2));
|
||||
_plugin->PropertyChanged.connect_same_thread (*this, std::bind (&IOPlug::property_changed_externally, this, _1, _2));
|
||||
_plugin->activate ();
|
||||
_plugin->set_insert (this, 0);
|
||||
}
|
||||
|
|
@ -372,6 +373,17 @@ IOPlug::parameter_changed_externally (uint32_t which, float val)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
IOPlug::property_changed_externally (uint32_t which, Variant val)
|
||||
{
|
||||
std::shared_ptr<Evoral::Control> c = control (Evoral::Parameter (PluginPropertyAutomation, 0, which));
|
||||
std::shared_ptr<PluginPropertyControl> pc = std::dynamic_pointer_cast<PluginPropertyControl> (c);
|
||||
|
||||
if (pc) {
|
||||
pc->catch_up_with_external_value (val.to_double ());
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
IOPlug::set_block_size (pframes_t n_samples)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -393,6 +393,14 @@ PlugInsertBase::PluginPropertyControl::actually_set_value (double user_val, Cont
|
|||
AutomationControl::actually_set_value (user_val, gcd);
|
||||
}
|
||||
|
||||
void
|
||||
PlugInsertBase::PluginPropertyControl::catch_up_with_external_value (double user_val)
|
||||
{
|
||||
if (user_val != Control::get_double ()) {
|
||||
PluginPropertyControl::actually_set_value (user_val, Controllable::NoGroup);
|
||||
}
|
||||
}
|
||||
|
||||
XMLNode&
|
||||
PlugInsertBase::PluginPropertyControl::get_state () const
|
||||
{
|
||||
|
|
|
|||
|
|
@ -660,6 +660,39 @@ PluginInsert::parameter_changed_externally (uint32_t which, float val)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginInsert::property_changed_externally (uint32_t which, Variant val)
|
||||
{
|
||||
std::shared_ptr<Evoral::Control> c = control (Evoral::Parameter (PluginPropertyAutomation, 0, which));
|
||||
std::shared_ptr<PluginPropertyControl> pc = std::dynamic_pointer_cast<PluginPropertyControl> (c);
|
||||
|
||||
if (pc) {
|
||||
pc->catch_up_with_external_value (val.to_double ());
|
||||
}
|
||||
|
||||
/* Second propagation: tell all plugins except the first to
|
||||
* update the value of this parameter. For sane plugin APIs,
|
||||
* there are no other plugins, so this is a no-op in those
|
||||
* cases.
|
||||
*/
|
||||
|
||||
Plugins::iterator i = _plugins.begin ();
|
||||
|
||||
/* don't set the first plugin, just all the slaves */
|
||||
|
||||
if (i != _plugins.end ()) {
|
||||
++i;
|
||||
for (; i != _plugins.end (); ++i) {
|
||||
(*i)->set_property (which, val);
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<Plugin> iasp = _impulseAnalysisPlugin.lock();
|
||||
if (iasp) {
|
||||
iasp->set_property (which, val);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
PluginInsert::set_block_size (pframes_t nframes)
|
||||
{
|
||||
|
|
@ -3021,6 +3054,7 @@ PluginInsert::add_plugin (std::shared_ptr<Plugin> plugin)
|
|||
/* first (and probably only) plugin instance - connect to relevant signals */
|
||||
|
||||
plugin->ParameterChangedExternally.connect_same_thread (*this, std::bind (&PluginInsert::parameter_changed_externally, this, _1, _2));
|
||||
plugin->PropertyChanged.connect_same_thread (*this, std::bind (&PluginInsert::property_changed_externally, this, _1, _2));
|
||||
plugin->StartTouch.connect_same_thread (*this, std::bind (&PluginInsert::start_touch, this, _1));
|
||||
plugin->EndTouch.connect_same_thread (*this, std::bind (&PluginInsert::end_touch, this, _1));
|
||||
_custom_sinks = plugin->get_info()->n_inputs;
|
||||
|
|
|
|||
|
|
@ -430,6 +430,7 @@ RegionFxPlugin::add_plugin (std::shared_ptr<Plugin> plugin)
|
|||
if (_plugins.empty ()) {
|
||||
/* first (and probably only) plugin instance - connect to relevant signals */
|
||||
plugin->ParameterChangedExternally.connect_same_thread (*this, std::bind (&RegionFxPlugin::parameter_changed_externally, this, _1, _2));
|
||||
plugin->PropertyChanged.connect_same_thread (*this, std::bind (&RegionFxPlugin::property_changed_externally, this, _1, _2));
|
||||
plugin->StartTouch.connect_same_thread (*this, std::bind (&RegionFxPlugin::start_touch, this, _1));
|
||||
plugin->EndTouch.connect_same_thread (*this, std::bind (&RegionFxPlugin::end_touch, this, _1));
|
||||
}
|
||||
|
|
@ -695,6 +696,34 @@ RegionFxPlugin::parameter_changed_externally (uint32_t which, float val)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
RegionFxPlugin::property_changed_externally (uint32_t which, Variant val)
|
||||
{
|
||||
std::shared_ptr<Evoral::Control> c = control (Evoral::Parameter (PluginPropertyAutomation, 0, which));
|
||||
std::shared_ptr<PluginPropertyControl> pc = std::dynamic_pointer_cast<PluginPropertyControl> (c);
|
||||
|
||||
if (pc) {
|
||||
pc->catch_up_with_external_value (val.to_double ());
|
||||
}
|
||||
|
||||
/* Second propagation: tell all plugins except the first to
|
||||
* update the value of this parameter. For sane plugin APIs,
|
||||
* there are no other plugins, so this is a no-op in those
|
||||
* cases.
|
||||
*/
|
||||
|
||||
Plugins::iterator i = _plugins.begin ();
|
||||
|
||||
/* don't set the first plugin, just all the slaves */
|
||||
|
||||
if (i != _plugins.end ()) {
|
||||
++i;
|
||||
for (; i != _plugins.end (); ++i) {
|
||||
(*i)->set_property (which, val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
RegionFxPlugin::describe_parameter (Evoral::Parameter param)
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue