plugin support for Controllable::NotAutomatable
[ardour.git] / libs / ardour / plugin_insert.cc
index 35ac613d7b01869c9be434c6ec05aefbfda9129f..291ccbfc54d0c3302614a92b781846292154f559 100644 (file)
@@ -409,31 +409,42 @@ PluginInsert::create_automatable_parameters ()
 {
        assert (!_plugins.empty());
 
+       boost::shared_ptr<Plugin> plugin = _plugins.front();
        set<Evoral::Parameter> a = _plugins.front()->automatable ();
 
-       for (set<Evoral::Parameter>::iterator i = a.begin(); i != a.end(); ++i) {
-               if (i->type() == PluginAutomation) {
+       for (uint32_t i = 0; i < plugin->parameter_count(); ++i) {
+               if (!plugin->parameter_is_control (i) || !plugin->parameter_is_input (i)) {
+                       continue;
+               }
+               Evoral::Parameter param (PluginAutomation, 0, i);
 
-                       Evoral::Parameter param(*i);
+               ParameterDescriptor desc;
+               plugin->get_parameter_descriptor(i, desc);
 
-                       ParameterDescriptor desc;
-                       _plugins.front()->get_parameter_descriptor(i->id(), desc);
+               const bool automatable = a.find(param) != a.end();
 
+               if (automatable) {
                        can_automate (param);
-                       boost::shared_ptr<AutomationList> list(new AutomationList(param, desc));
-                       boost::shared_ptr<AutomationControl> c (new PluginControl(this, param, desc, list));
-                       add_control (c);
-                       _plugins.front()->set_automation_control (i->id(), c);
-               } else if (i->type() == PluginPropertyAutomation) {
-                       Evoral::Parameter param(*i);
-                       const ParameterDescriptor& desc = _plugins.front()->get_property_descriptor(param.id());
-                       if (desc.datatype != Variant::NOTHING) {
-                               boost::shared_ptr<AutomationList> list;
-                               if (Variant::type_is_numeric(desc.datatype)) {
-                                       list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
-                               }
-                               add_control (boost::shared_ptr<AutomationControl> (new PluginPropertyControl(this, param, desc, list)));
+               }
+               boost::shared_ptr<AutomationList> list(new AutomationList(param, desc));
+               boost::shared_ptr<AutomationControl> c (new PluginControl(this, param, desc, list));
+               if (!automatable) {
+                       c->set_flags (Controllable::Flag ((int)c->flags() | Controllable::NotAutomatable));
+               }
+               add_control (c);
+               plugin->set_automation_control (i, c);
+       }
+
+       const Plugin::PropertyDescriptors& pdl (plugin->get_supported_properties ());
+       for (Plugin::PropertyDescriptors::const_iterator p = pdl.begin(); p != pdl.end(); ++p) {
+               Evoral::Parameter param (PluginPropertyAutomation, 0, p->first);
+               const ParameterDescriptor& desc = plugin->get_property_descriptor(param.id());
+               if (desc.datatype != Variant::NOTHING) {
+                       boost::shared_ptr<AutomationList> list;
+                       if (Variant::type_is_numeric(desc.datatype)) {
+                               list = boost::shared_ptr<AutomationList>(new AutomationList(param, desc));
                        }
+                       add_control (boost::shared_ptr<AutomationControl> (new PluginPropertyControl(this, param, desc, list)));
                }
        }
 }
@@ -1330,6 +1341,30 @@ PluginInsert::check_inplace ()
                        inplace_ok = false;
                }
        }
+
+       if (inplace_ok) {
+               /* check if every output is fed by the corresponding input
+                *
+                * this prevents  in-port 1 -> sink-pin 2  ||  source-pin 1 -> out port 1, source-pin 2 -> out port 2
+                * (with in-place,  source-pin 1 -> out port 1 overwrites in-port 1)
+                *
+                * but allows     in-port 1 -> sink-pin 2  ||  source-pin 2 -> out port 1
+                */
+               ChanMapping in_map (input_map ());
+               const ChanMapping::Mappings out_m (output_map ().mappings ());
+               for (ChanMapping::Mappings::const_iterator t = out_m.begin (); t != out_m.end () && inplace_ok; ++t) {
+                       for (ChanMapping::TypeMapping::const_iterator c = (*t).second.begin (); c != (*t).second.end () ; ++c) {
+                               /* src-pin: c->first, out-port: c->second */
+                               bool valid;
+                               uint32_t in_port = in_map.get (t->first, c->first, &valid);
+                               if (valid && in_port != c->second) {
+                                       inplace_ok = false;
+                                       break;
+                               }
+                       }
+               }
+       }
+
        DEBUG_TRACE (DEBUG::ChanMapping, string_compose ("%1: %2\n", name(), inplace_ok ? "In-Place" : "No Inplace Processing"));
        return !inplace_ok; // no-inplace
 }
@@ -2583,29 +2618,12 @@ PluginInsert::PluginControl::PluginControl (PluginInsert*                     p,
                        list->set_interpolation(Evoral::ControlList::Discrete);
                }
        }
-
-       if (desc.toggled) {
-               set_flags(Controllable::Toggle);
-       }
 }
 
 /** @param val `user' value */
-void
-PluginInsert::PluginControl::set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
-{
-       if (writable()) {
-               _set_value (user_val, group_override);
-       }
-}
-void
-PluginInsert::PluginControl::set_value_unchecked (double user_val)
-{
-       /* used only by automation playback */
-       _set_value (user_val, Controllable::NoGroup);
-}
 
 void
-PluginInsert::PluginControl::_set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
+PluginInsert::PluginControl::actually_set_value (double user_val, PBD::Controllable::GroupControlDisposition group_override)
 {
        /* FIXME: probably should be taking out some lock here.. */
 
@@ -2618,13 +2636,13 @@ PluginInsert::PluginControl::_set_value (double user_val, PBD::Controllable::Gro
                iasp->set_parameter (_list->parameter().id(), user_val);
        }
 
-       AutomationControl::set_value (user_val, group_override);
+       AutomationControl::actually_set_value (user_val, group_override);
 }
 
 void
 PluginInsert::PluginControl::catch_up_with_external_value (double user_val)
 {
-       AutomationControl::set_value (user_val, Controllable::NoGroup);
+       AutomationControl::actually_set_value (user_val, Controllable::NoGroup);
 }
 
 XMLNode&
@@ -2669,22 +2687,10 @@ PluginInsert::PluginPropertyControl::PluginPropertyControl (PluginInsert*
                alist()->set_yrange (desc.lower, desc.upper);
                alist()->reset_default (desc.normal);
        }
-
-       if (desc.toggled) {
-               set_flags(Controllable::Toggle);
-       }
-}
-
-void
-PluginInsert::PluginPropertyControl::set_value (double user_val, PBD::Controllable::GroupControlDisposition /* group_override*/)
-{
-       if (writable()) {
-               set_value_unchecked (user_val);
-       }
 }
 
 void
-PluginInsert::PluginPropertyControl::set_value_unchecked (double user_val)
+PluginInsert::PluginPropertyControl::actually_set_value (double user_val, Controllable::GroupControlDisposition gcd)
 {
        /* Old numeric set_value(), coerce to appropriate datatype if possible.
           This is lossy, but better than nothing until Ardour's automation system
@@ -2700,7 +2706,8 @@ PluginInsert::PluginPropertyControl::set_value_unchecked (double user_val)
        }
 
        _value = value;
-       AutomationControl::set_value (user_val, Controllable::NoGroup);
+
+       AutomationControl::actually_set_value (user_val, gcd);
 }
 
 XMLNode&