X-Git-Url: https://main.carlh.net/gitweb/?a=blobdiff_plain;f=libs%2Fardour%2Fplugin_insert.cc;h=e9bea95dc9067e0856d2396aca988735d0c242df;hb=d6b36a13a127d9b152cfe12d596ea862773f9923;hp=a7e512713df73cfb4fa1ffa6debad362ce4b732c;hpb=7cc2e8c969e7b778af90f3b45a4c3fa3cbc90ef6;p=ardour.git diff --git a/libs/ardour/plugin_insert.cc b/libs/ardour/plugin_insert.cc index a7e512713d..e9bea95dc9 100644 --- a/libs/ardour/plugin_insert.cc +++ b/libs/ardour/plugin_insert.cc @@ -50,6 +50,10 @@ #include "ardour/lxvst_plugin.h" #endif +#ifdef MACVST_SUPPORT +#include "ardour/mac_vst_plugin.h" +#endif + #ifdef AUDIOUNIT_SUPPORT #include "ardour/audio_unit.h" #endif @@ -77,6 +81,7 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr plug) , _strict_io (false) , _custom_cfg (false) , _maps_from_state (false) + , _latency_changed (false) , _bypass_port (UINT32_MAX) { /* the first is the master */ @@ -93,6 +98,9 @@ PluginInsert::PluginInsert (Session& s, boost::shared_ptr plug) PluginInsert::~PluginInsert () { + for (CtrlOutMap::const_iterator i = _control_outputs.begin(); i != _control_outputs.end(); ++i) { + boost::dynamic_pointer_cast(i->second)->drop_references (); + } } void @@ -393,13 +401,13 @@ PluginInsert::plugin_latency () const { } bool -PluginInsert::needs_midi_input() const +PluginInsert::is_instrument() const { PluginInfoPtr pip = _plugins[0]->get_info(); - if (pip->needs_midi_input ()) { + if (pip->is_instrument ()) { return true; } - return pip->n_inputs.n_midi() != 0 && pip->n_outputs.n_audio() != 0; + return pip->n_inputs.n_midi () != 0 && pip->n_outputs.n_audio () > 0 && pip->n_inputs.n_audio () == 0; } bool @@ -425,7 +433,14 @@ PluginInsert::has_output_presets (ChanCount in, ChanCount out) return false; } } - if (!needs_midi_input ()) { + + if (ppc.size () == 1 && ppc.find (0) != ppc.end () && !_plugins[0]->get_info ()->reconfigurable_io ()) { + // some midi-sequencer (e.g. QMidiArp) or other midi-out plugin + // pretending to be an "Instrument" + return false; + } + + if (!is_instrument ()) { return false; } return true; @@ -440,7 +455,11 @@ PluginInsert::create_automatable_parameters () set a = _plugins.front()->automatable (); for (uint32_t i = 0; i < plugin->parameter_count(); ++i) { - if (!plugin->parameter_is_control (i) || !plugin->parameter_is_input (i)) { + if (!plugin->parameter_is_control (i)) { + continue; + } + if (!plugin->parameter_is_input (i)) { + _control_outputs[i] = boost::shared_ptr (new ReadOnlyControl (plugin, i)); continue; } Evoral::Parameter param (PluginAutomation, 0, i); @@ -478,6 +497,21 @@ PluginInsert::create_automatable_parameters () _bypass_port = plugin->designated_bypass_port (); + /* special case VST effSetBypass */ + if (_bypass_port == UINT32_MAX -1) { + // emulate VST Bypass + Evoral::Parameter param (PluginAutomation, 0, _bypass_port); + ParameterDescriptor desc; + desc.label = _("Plugin Enable"); + desc.toggled = true; + desc.normal = 1; + desc.lower = 0; + desc.upper = 1; + boost::shared_ptr list(new AutomationList(param, desc)); + boost::shared_ptr c (new PluginControl(this, param, desc, list)); + add_control (c); + } + if (_bypass_port != UINT32_MAX) { boost::shared_ptr ac = automation_control (Evoral::Parameter (PluginAutomation, 0, _bypass_port)); if (0 == (ac->flags () & Controllable::NotAutomatable)) { @@ -485,7 +519,9 @@ PluginInsert::create_automatable_parameters () ac->Changed.connect_same_thread (*this, boost::bind (&PluginInsert::enable_changed, this)); } } + plugin->PresetPortSetValue.connect_same_thread (*this, boost::bind (&PluginInsert::preset_load_set_value, this, _1, _2)); } + /** Called when something outside of this host has modified a plugin * parameter. Responsible for propagating the change to two places: * @@ -555,6 +591,13 @@ PluginInsert::activate () } Processor::activate (); + /* when setting state e.g ProcessorBox::paste_processor_state () + * the plugin is not yet owned by a route. + * but no matter. Route::add_processors() will call activate () again + */ + if (!owner ()) { + return; + } if (_plugin_signal_latency != signal_latency ()) { _plugin_signal_latency = signal_latency (); latency_changed (); @@ -597,7 +640,27 @@ PluginInsert::enable (bool yn) activate (); } boost::shared_ptr ac = automation_control (Evoral::Parameter (PluginAutomation, 0, _bypass_port)); - ac->set_value (yn ? 1.0 : 0.0, Controllable::NoGroup); + const double val = yn ? 1.0 : 0.0; + ac->set_value (val, Controllable::NoGroup); + +#ifdef ALLOW_VST_BYPASS_TO_FAIL // yet unused, see also vst_plugin.cc + /* special case VST.. bypass may fail */ + if (_bypass_port == UINT32_MAX - 1) { + /* check if bypass worked */ + if (ac->get_value () != val) { + warning << _("PluginInsert: VST Bypass failed, falling back to host bypass.") << endmsg; + // set plugin to enabled (not-byassed) + ac->set_value (1.0, Controllable::NoGroup); + // ..and use host-provided hard-bypass + if (yn) { + activate (); + } else { + deactivate (); + } + return; + } + } +#endif ActiveChanged (); } } @@ -637,6 +700,23 @@ PluginInsert::bypassable_changed () BypassableChanged (); } +void +PluginInsert::preset_load_set_value (uint32_t p, float v) +{ + boost::shared_ptr ac = automation_control (Evoral::Parameter(PluginAutomation, 0, p)); + if (!ac) { + return; + } + + if (ac->automation_state() & Play) { + return; + } + + start_touch (p); + ac->set_value (v, Controllable::NoGroup); + end_touch (p); +} + void PluginInsert::inplace_silence_unconnected (BufferSet& bufs, const PinMappings& out_map, framecnt_t nframes, framecnt_t offset) const { @@ -1083,7 +1163,8 @@ PluginInsert::run (BufferSet& bufs, framepos_t start_frame, framepos_t end_frame if (_session.transport_rolling() || _session.bounce_processing()) { automation_run (bufs, start_frame, end_frame, speed, nframes); } else { - connect_and_run (bufs, start_frame, end_frame, speed, nframes, 0, false); + Glib::Threads::Mutex::Lock lm (control_lock(), Glib::Threads::TRY_LOCK); + connect_and_run (bufs, start_frame, end_frame, speed, nframes, 0, lm.locked()); } } else { @@ -1233,6 +1314,9 @@ PluginInsert::plugin_factory (boost::shared_ptr other) #ifdef LXVST_SUPPORT boost::shared_ptr lxvp; #endif +#ifdef MACVST_SUPPORT + boost::shared_ptr mvp; +#endif #ifdef AUDIOUNIT_SUPPORT boost::shared_ptr ap; #endif @@ -1253,6 +1337,10 @@ PluginInsert::plugin_factory (boost::shared_ptr other) } else if ((lxvp = boost::dynamic_pointer_cast (other)) != 0) { return boost::shared_ptr (new LXVSTPlugin (*lxvp)); #endif +#ifdef MACVST_SUPPORT + } else if ((mvp = boost::dynamic_pointer_cast (other)) != 0) { + return boost::shared_ptr (new MacVSTPlugin (*mvp)); +#endif #ifdef AUDIOUNIT_SUPPORT } else if ((ap = boost::dynamic_pointer_cast (other)) != 0) { return boost::shared_ptr (new AUPlugin (*ap)); @@ -1796,11 +1884,9 @@ PluginInsert::configure_io (ChanCount in, ChanCount out) && _in_map.size() == _out_map.size() && _in_map.size() == get_count () ) { - assert (_maps_from_state == false); /* If the configuration has not changed, keep the mapping */ mapping_changed = sanitize_maps (); } else if (_match.custom_cfg && _configured) { - assert (_maps_from_state == false); /* don't touch the map in manual mode */ mapping_changed = sanitize_maps (); } else { @@ -1985,7 +2071,7 @@ PluginInsert::internal_can_support_io_configuration (ChanCount const & inx, Chan m.strict_io = true; /* special case MIDI instruments */ - if (needs_midi_input ()) { + if (is_instrument ()) { // output = midi-bypass + at most master-out channels. ChanCount max_out (DataType::AUDIO, 2); // TODO use master-out max_out.set (DataType::MIDI, out.get(DataType::MIDI)); @@ -2161,7 +2247,7 @@ PluginInsert::automatic_can_support_io_configuration (ChanCount const & inx, Cha uint32_t f = 0; bool can_replicate = true; - for (DataType::iterator t = DataType::begin(); t != DataType::end() && can_replicate; ++t) { + for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) { // ignore side-chains uint32_t nin = ns_inputs.get (*t); @@ -2364,6 +2450,8 @@ PluginInsert::set_state(const XMLNode& node, int version) type = ARDOUR::Windows_VST; } else if (prop->value() == X_("lxvst")) { type = ARDOUR::LXVST; + } else if (prop->value() == X_("mac-vst")) { + type = ARDOUR::MacVST; } else if (prop->value() == X_("audiounit")) { type = ARDOUR::AudioUnit; } else if (prop->value() == X_("luaproc")) { @@ -2379,9 +2467,7 @@ PluginInsert::set_state(const XMLNode& node, int version) if (prop == 0) { #ifdef WINDOWS_VST_SUPPORT - /* older sessions contain VST plugins with only an "id" field. - */ - + /* older sessions contain VST plugins with only an "id" field. */ if (type == ARDOUR::Windows_VST) { prop = node.property ("id"); } @@ -2389,11 +2475,11 @@ PluginInsert::set_state(const XMLNode& node, int version) #ifdef LXVST_SUPPORT /*There shouldn't be any older sessions with linuxVST support.. but anyway..*/ - if (type == ARDOUR::LXVST) { prop = node.property ("id"); } #endif + /* recheck */ if (prop == 0) { @@ -2404,22 +2490,29 @@ PluginInsert::set_state(const XMLNode& node, int version) boost::shared_ptr plugin = find_plugin (_session, prop->value(), type); - /* treat linux and windows VST plugins equivalent if they have the same uniqueID + /* treat VST plugins equivalent if they have the same uniqueID * allow to move sessions windows <> linux */ #ifdef LXVST_SUPPORT - if (plugin == 0 && type == ARDOUR::Windows_VST) { + if (plugin == 0 && (type == ARDOUR::Windows_VST || type == ARDOUR::MacVST)) { type = ARDOUR::LXVST; plugin = find_plugin (_session, prop->value(), type); } #endif #ifdef WINDOWS_VST_SUPPORT - if (plugin == 0 && type == ARDOUR::LXVST) { + if (plugin == 0 && (type == ARDOUR::LXVST || type == ARDOUR::MacVST)) { type = ARDOUR::Windows_VST; plugin = find_plugin (_session, prop->value(), type); } #endif +#ifdef MACVST_SUPPORT + if (plugin == 0 && (type == ARDOUR::Windows_VST || type == ARDOUR::LXVST)) { + type = ARDOUR::MacVST; + plugin = find_plugin (_session, prop->value(), type); + } +#endif + if (plugin == 0 && type == ARDOUR::Lua) { /* unique ID (sha1 of script) was not found, * load the plugin from the serialized version in the @@ -2514,6 +2607,14 @@ PluginInsert::set_state(const XMLNode& node, int version) } } + /* when copying plugin state, notify UI */ + for (Controls::const_iterator li = controls().begin(); li != controls().end(); ++li) { + boost::shared_ptr c = boost::dynamic_pointer_cast (li->second); + if (c) { + c->Changed (false, Controllable::NoGroup); /* EMIT SIGNAL */ + } + } + break; } } @@ -2579,7 +2680,9 @@ PluginInsert::set_state(const XMLNode& node, int version) if (!_sidechain) { add_sidechain (0); } - _sidechain->set_state (**i, version); + if (!regenerate_xml_or_string_ids ()) { + _sidechain->set_state (**i, version); + } } } @@ -2608,6 +2711,15 @@ PluginInsert::update_id (PBD::ID id) } } +void +PluginInsert::set_owner (SessionObject* o) +{ + Processor::set_owner (o); + for (Plugins::iterator i = _plugins.begin(); i != _plugins.end(); ++i) { + (*i)->set_owner (o); + } +} + void PluginInsert::set_state_dir (const std::string& d) { @@ -2698,6 +2810,16 @@ PluginInsert::set_parameter_state_2X (const XMLNode& node, int version) } } +boost::shared_ptr +PluginInsert::control_output (uint32_t num) const +{ + CtrlOutMap::const_iterator i = _control_outputs.find (num); + if (i == _control_outputs.end ()) { + return boost::shared_ptr (); + } else { + return (*i).second; + } +} string PluginInsert::describe_parameter (Evoral::Parameter param) @@ -2873,6 +2995,7 @@ PluginInsert::get_impulse_analysis_plugin() assert (out == internal_output_streams ()); } ret->configure_io (internal_input_streams (), out); + ret->set_owner (_owner); _impulseAnalysisPlugin = ret; } else { ret = _impulseAnalysisPlugin.lock(); @@ -2898,6 +3021,7 @@ void PluginInsert::add_plugin (boost::shared_ptr plugin) { plugin->set_insert_id (this->id()); + plugin->set_owner (_owner); if (_plugins.empty()) { /* first (and probably only) plugin instance - connect to relevant signals */ @@ -2918,7 +3042,7 @@ PluginInsert::add_plugin (boost::shared_ptr plugin) } } } -#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT) +#if (defined WINDOWS_VST_SUPPORT || defined LXVST_SUPPORT || defined MACVST_SUPPORT) boost::shared_ptr vst = boost::dynamic_pointer_cast (plugin); if (vst) { vst->set_insert (this, _plugins.size ()); @@ -2977,19 +3101,21 @@ PluginInsert::latency_changed () void PluginInsert::start_touch (uint32_t param_id) { - boost::shared_ptr ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id)); - if (ac) { - ac->start_touch (session().audible_frame()); - } + boost::shared_ptr ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id)); + if (ac) { + // ToDo subtract _plugin_signal_latency from audible_frame() when rolling, assert > 0 + ac->start_touch (session().audible_frame()); + } } void PluginInsert::end_touch (uint32_t param_id) { - boost::shared_ptr ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id)); - if (ac) { - ac->stop_touch (true, session().audible_frame()); - } + boost::shared_ptr ac = automation_control (Evoral::Parameter (PluginAutomation, 0, param_id)); + if (ac) { + // ToDo subtract _plugin_signal_latency from audible_frame() when rolling, assert > 0 + ac->stop_touch (true, session().audible_frame()); + } } std::ostream& operator<<(std::ostream& o, const ARDOUR::PluginInsert::Match& m)