prepare plugin configuration and replacing instruments
authorRobin Gareus <robin@gareus.org>
Thu, 19 May 2016 14:29:08 +0000 (16:29 +0200)
committerRobin Gareus <robin@gareus.org>
Thu, 19 May 2016 14:29:08 +0000 (16:29 +0200)
libs/ardour/ardour/plugin_insert.h
libs/ardour/ardour/rc_configuration_vars.h
libs/ardour/ardour/route.h
libs/ardour/plugin_insert.cc
libs/ardour/route.cc

index db052f0f0d174971301ac1dd06a46667e3482a3f..4b5f38964a3f528ad4dd2e09edeac9c359e7caa1 100644 (file)
@@ -93,6 +93,8 @@ class LIBARDOUR_API PluginInsert : public Processor
                return _thru_map;
        }
 
+       bool pre_seed (const ChanCount&, const ChanCount&, const ChanMapping&, const ChanMapping&, const ChanMapping&);
+
        ChanMapping input_map () const; ///< combined (all instances) input map
        ChanMapping output_map () const; ///< combined (all instances) output map
        bool has_midi_bypass () const;
index d0b9ca457f5358638645f50105f052d48e04c822..4bd89e2514f41c4281aae46b42a0cf65ffaeeef0 100644 (file)
@@ -239,6 +239,8 @@ CONFIG_VARIABLE (bool, discover_vst_on_start, "discover-vst-on-start", false)
 CONFIG_VARIABLE (bool, verbose_plugin_scan, "verbose-plugin-scan", true)
 CONFIG_VARIABLE (int, vst_scan_timeout, "vst-scan-timeout", 600) /* deciseconds, per plugin, <= 0 no timeout */
 CONFIG_VARIABLE (bool, discover_audio_units, "discover-audio-units", false)
+CONFIG_VARIABLE (bool, ask_replace_instrument, "ask-replace-instrument", true)
+CONFIG_VARIABLE (bool, ask_setup_instrument, "ask-setup-instrument", true)
 
 /* custom user plugin paths */
 CONFIG_VARIABLE (std::string, plugin_path_vst, "plugin-path-vst", "@default@")
index 3c06018e1bc969505e204b8e216a408f4e383a13..3ade22319d28a7c555aeb68914a0231dd984b249 100644 (file)
@@ -64,6 +64,7 @@ class Panner;
 class PannerShell;
 class PortSet;
 class Processor;
+class PluginInsert;
 class RouteGroup;
 class Send;
 class InternalReturn;
@@ -372,6 +373,14 @@ public:
                PropertyChanged (ARDOUR::Properties::name);
        }
 
+       enum PluginSetupOptions {
+               None = 0x0,
+               CanReplace = 0x1,
+               MultiOut = 0x2,
+       };
+
+       static PBD::Signal3<int,boost::shared_ptr<Route>, boost::shared_ptr<PluginInsert>, PluginSetupOptions > PluginSetup;
+
        /** the processors have changed; the parameter indicates what changed */
        PBD::Signal1<void,RouteProcessorChange> processors_changed;
        PBD::Signal1<void,void*> record_enable_changed;
index f6f620e88350cc583ac983da610ab57d1cdecdcf..a72412a86875fbc99d99520249287265802b2da1 100644 (file)
@@ -1192,6 +1192,20 @@ PluginInsert::set_thru_map (ChanMapping m) {
        }
 }
 
+bool
+PluginInsert::pre_seed (const ChanCount& in, const ChanCount& out,
+               const ChanMapping& im, const ChanMapping& om, const ChanMapping& tm)
+{
+       if (_configured) { return false; }
+       _configured_in = in;
+       _configured_out = out;
+       _in_map[0] = im;
+       _out_map[0] = om;
+       _thru_map = tm;
+       _maps_from_state = in.n_total () > 0 && out.n_total () > 0;
+       return true;
+}
+
 ChanMapping
 PluginInsert::input_map () const
 {
index 8a98149fa05f55f6bdbaddca9647479d6b2f2d80..3442d0ec8aca145c56c0bc774ec8f06bd1e4c3b5 100644 (file)
@@ -78,6 +78,7 @@ using namespace PBD;
 
 PBD::Signal0<void> Route::SyncOrderKeys;
 PBD::Signal0<void> Route::RemoteControlIDChange;
+PBD::Signal3<int,boost::shared_ptr<Route>, boost::shared_ptr<PluginInsert>, Route::PluginSetupOptions > Route::PluginSetup;
 
 /** Base class for all routable/mixable objects (tracks and busses) */
 Route::Route (Session& sess, string name, Flag flg, DataType default_type)
@@ -1369,6 +1370,15 @@ Route::add_processor_from_xml_2X (const XMLNode& node, int version)
        }
 }
 
+
+inline Route::PluginSetupOptions operator|= (Route::PluginSetupOptions& a, const Route::PluginSetupOptions& b) {
+       return a = static_cast<Route::PluginSetupOptions> (static_cast <int>(a) | static_cast<int> (b));
+}
+
+inline Route::PluginSetupOptions operator&= (Route::PluginSetupOptions& a, const Route::PluginSetupOptions& b) {
+       return a = static_cast<Route::PluginSetupOptions> (static_cast <int>(a) & static_cast<int> (b));
+}
+
 int
 Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor> before, ProcessorStreams* err)
 {
@@ -1392,6 +1402,59 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
                return 0;
        }
 
+       ProcessorList to_skip;
+
+       // check if there's an instrument to replace or configure
+       for (ProcessorList::const_iterator i = others.begin(); i != others.end(); ++i) {
+               boost::shared_ptr<PluginInsert> pi;
+               if ((pi = boost::dynamic_pointer_cast<PluginInsert>(*i)) == 0) {
+                       continue;
+               }
+               if (!pi->plugin ()->get_info ()->is_instrument ()) {
+                       continue;
+               }
+               boost::shared_ptr<Processor> instrument = the_instrument ();
+               ChanCount in (DataType::MIDI, 1);
+               ChanCount out (DataType::AUDIO, 2); // XXX route's out?!
+
+               PluginSetupOptions flags = None;
+               if (instrument) {
+                       flags |= CanReplace;
+                       in = instrument->input_streams ();
+                       out = instrument->output_streams ();
+               }
+               if (pi->has_output_presets (in, out)) {
+                       flags |= MultiOut;
+               }
+
+               pi->set_strict_io (_strict_io);
+
+               PluginSetupOptions mask = None;
+               if (Config->get_ask_replace_instrument ()) {
+                       mask |= CanReplace;
+               }
+               if (Config->get_ask_setup_instrument ()) {
+                       mask |= MultiOut;
+               }
+
+               flags &= mask;
+
+               if (flags != None) {
+                       boost::optional<int> rv = PluginSetup (shared_from_this (), pi, flags);  /* EMIT SIGNAL */
+                       switch (rv.get_value_or (0)) {
+                               case 1:
+                                       to_skip.push_back (*i); // don't add this one;
+                                       break;
+                               case 2:
+                                       replace_processor (instrument, *i, err);
+                                       to_skip.push_back (*i);
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
+       }
+
        {
                Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
                Glib::Threads::RWLock::WriterLock lm (_processor_lock);
@@ -1402,6 +1465,10 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
                        if (*i == _meter) {
                                continue;
                        }
+                       ProcessorList::iterator check = find (to_skip.begin(), to_skip.end(), *i);
+                       if (check != to_skip.end()) {
+                               continue;
+                       }
 
                        boost::shared_ptr<PluginInsert> pi;