mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-07 07:14:56 +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;
|
std::string ensure_io_name (std::string) const;
|
||||||
void create_parameters ();
|
void create_parameters ();
|
||||||
void parameter_changed_externally (uint32_t, float);
|
void parameter_changed_externally (uint32_t, float);
|
||||||
|
void property_changed_externally (uint32_t, Variant);
|
||||||
|
|
||||||
void setup ();
|
void setup ();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,7 @@ public:
|
||||||
std::shared_ptr<AutomationList> list = std::shared_ptr<AutomationList> ());
|
std::shared_ptr<AutomationList> list = std::shared_ptr<AutomationList> ());
|
||||||
|
|
||||||
virtual double get_value (void) const;
|
virtual double get_value (void) const;
|
||||||
|
void catch_up_with_external_value (double val);
|
||||||
XMLNode& get_state () const;
|
XMLNode& get_state () const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
|
||||||
|
|
@ -276,6 +276,7 @@ private:
|
||||||
PluginInsert (const PluginInsert&);
|
PluginInsert (const PluginInsert&);
|
||||||
|
|
||||||
void parameter_changed_externally (uint32_t, float);
|
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);
|
void set_parameter (Evoral::Parameter param, float val, sampleoffset_t);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -165,6 +165,7 @@ private:
|
||||||
bool check_inplace ();
|
bool check_inplace ();
|
||||||
void create_parameters ();
|
void create_parameters ();
|
||||||
void parameter_changed_externally (uint32_t, float);
|
void parameter_changed_externally (uint32_t, float);
|
||||||
|
void property_changed_externally (uint32_t, Variant);
|
||||||
void automation_run (samplepos_t start, pframes_t nframes);
|
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;
|
bool find_next_event (timepos_t const& start, timepos_t const& end, Evoral::ControlEvent& next_event) const;
|
||||||
void start_touch (uint32_t param_id);
|
void start_touch (uint32_t param_id);
|
||||||
|
|
|
||||||
|
|
@ -256,6 +256,7 @@ IOPlug::setup ()
|
||||||
|
|
||||||
_plugin->reconfigure_io (_n_in, aux_in, _n_out);
|
_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->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->activate ();
|
||||||
_plugin->set_insert (this, 0);
|
_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
|
int
|
||||||
IOPlug::set_block_size (pframes_t n_samples)
|
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);
|
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&
|
XMLNode&
|
||||||
PlugInsertBase::PluginPropertyControl::get_state () const
|
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
|
int
|
||||||
PluginInsert::set_block_size (pframes_t nframes)
|
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 */
|
/* 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->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->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));
|
plugin->EndTouch.connect_same_thread (*this, std::bind (&PluginInsert::end_touch, this, _1));
|
||||||
_custom_sinks = plugin->get_info()->n_inputs;
|
_custom_sinks = plugin->get_info()->n_inputs;
|
||||||
|
|
|
||||||
|
|
@ -430,6 +430,7 @@ RegionFxPlugin::add_plugin (std::shared_ptr<Plugin> plugin)
|
||||||
if (_plugins.empty ()) {
|
if (_plugins.empty ()) {
|
||||||
/* first (and probably only) plugin instance - connect to relevant signals */
|
/* 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->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->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));
|
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
|
std::string
|
||||||
RegionFxPlugin::describe_parameter (Evoral::Parameter param)
|
RegionFxPlugin::describe_parameter (Evoral::Parameter param)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue