+ std::vector<ControlUI *> control_uis;
+ bool grid = plugin->parameter_count() > 0;
+
+ // Build a ControlUI for each control port
+ for (size_t i = 0; i < plugin->parameter_count(); ++i) {
+
+ if (plugin->parameter_is_control (i)) {
+
+ /* Don't show latency control ports */
+
+ const Evoral::Parameter param(PluginAutomation, 0, i);
+ if (plugin->describe_parameter (param) == X_("latency")) {
+ continue;
+ }
+
+ if (plugin->describe_parameter (param) == X_("hidden")) {
+ continue;
+ }
+
+ const float value = plugin->get_parameter(i);
+
+ ControlUI* cui;
+ Plugin::UILayoutHint hint;
+
+ if (!plugin->get_layout(i, hint)) {
+ grid = false;
+ }
+
+ boost::shared_ptr<ARDOUR::AutomationControl> c
+ = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
+ insert->control(param));
+
+ ParameterDescriptor desc;
+ plugin->get_parameter_descriptor(i, desc);
+ if ((cui = build_control_ui (param, desc, c, value, plugin->parameter_is_input(i), hint.knob)) == 0) {
+ error << string_compose(_("Plugin Editor: could not build control element for port %1"), i) << endmsg;
+ continue;
+ }
+
+ if (grid) {
+ cui->x0 = hint.x0;
+ cui->x1 = hint.x1;
+ cui->y0 = hint.y0;
+ cui->y1 = hint.y1;
+ }
+
+ const std::string param_docs = plugin->get_parameter_docs(i);
+ if (!param_docs.empty()) {
+ set_tooltip(cui, param_docs.c_str());
+ }
+
+ control_uis.push_back(cui);
+ }
+ }
+
+ // Build a ControlUI for each property
+ const Plugin::PropertyDescriptors& descs = plugin->get_supported_properties();
+ for (Plugin::PropertyDescriptors::const_iterator d = descs.begin(); d != descs.end(); ++d) {
+ const ParameterDescriptor& desc = d->second;
+ const Evoral::Parameter param(PluginPropertyAutomation, 0, desc.key);
+
+ boost::shared_ptr<ARDOUR::AutomationControl> c
+ = boost::dynamic_pointer_cast<ARDOUR::AutomationControl>(
+ insert->control(param));
+
+ if (!c) {
+ error << string_compose(_("Plugin Editor: no control for property %1"), desc.key) << endmsg;
+ continue;
+ }
+
+ ControlUI* cui = build_control_ui(param, desc, c, c->get_value(), true);
+ if (!cui) {
+ error << string_compose(_("Plugin Editor: could not build control element for property %1"),
+ desc.key) << endmsg;
+ continue;
+ }
+
+ control_uis.push_back(cui);
+ }
+ if (!descs.empty()) {
+ plugin->announce_property_values();
+ }
+
+ if (grid) {
+ custom_layout (control_uis);
+ } else {
+ automatic_layout (control_uis);
+ }
+
+ output_update ();
+
+ automation_manual_all_button.signal_clicked.connect(sigc::bind (sigc::mem_fun (*this, &GenericPluginUI::set_all_automation), ARDOUR::Off));
+ automation_play_all_button.signal_clicked.connect(sigc::bind (sigc::mem_fun (*this, &GenericPluginUI::set_all_automation), ARDOUR::Play));
+ automation_write_all_button.signal_clicked.connect(sigc::bind (sigc::mem_fun (*this, &GenericPluginUI::set_all_automation), ARDOUR::Write));
+ automation_touch_all_button.signal_clicked.connect(sigc::bind (sigc::mem_fun (*this, &GenericPluginUI::set_all_automation), ARDOUR::Touch));
+
+ /* XXX This is a workaround for AutomationControl not knowing about preset loads */
+ plugin->PresetLoaded.connect (*this, invalidator (*this), boost::bind (&GenericPluginUI::update_input_displays, this), gui_context ());
+}
+
+
+void
+GenericPluginUI::automatic_layout (const std::vector<ControlUI*>& control_uis)
+{