fix crash when copy'ing latent plugins
[ardour.git] / libs / ardour / route.cc
index 9660e78358b8881f0590d435a61e16b41206ef36..11db73241cbd304c629a556828f02611134678c9 100644 (file)
@@ -74,7 +74,7 @@
 #include "ardour/utils.h"
 #include "ardour/vca.h"
 
-#include "i18n.h"
+#include "pbd/i18n.h"
 
 using namespace std;
 using namespace ARDOUR;
@@ -229,10 +229,6 @@ Route::init ()
                _monitor_control->activate ();
        }
 
-       if (is_master() || is_monitor() || is_auditioner()) {
-               _mute_master->set_solo_ignore (true);
-       }
-
        /* now that we have _meter, its safe to connect to this */
 
        {
@@ -1018,8 +1014,12 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
                                }
                        }
 
+                       if (pi && pi->has_sidechain ()) {
+                               pi->sidechain_input ()->changed.connect_same_thread (*this, boost::bind (&Route::sidechain_change_handler, this, _1, _2));
+                       }
+
                        if ((*i)->active()) {
-                               // why?  emit  ActiveChanged() ??
+                               // emit ActiveChanged() and latency_changed() if needed
                                (*i)->activate ();
                        }
 
@@ -1636,8 +1636,9 @@ Route::try_configure_processors_unlocked (ChanCount in, ProcessorStreams* err)
                                 * Delivery::configure_io() will do the actual removal
                                 * by calling _output->ensure_io()
                                 */
-                               if (!is_master() && _session.master_out ()) {
-                                       /* ..but at least as many as there are master-inputs */
+                               if (!is_master() && _session.master_out () && in.n_audio() > 0) {
+                                       /* ..but at least as many as there are master-inputs, if
+                                        * the delivery is dealing with audio */
                                        // XXX this may need special-casing for mixbus (master-outputs)
                                        // and should maybe be a preference anyway ?!
                                        out = ChanCount::max (in, _session.master_out ()->n_inputs ());
@@ -2351,10 +2352,6 @@ Route::set_state (const XMLNode& node, int version)
                _strict_io = string_is_affirmative (prop->value());
        }
 
-       if (!can_solo()) {
-               _mute_master->set_solo_ignore (true);
-       }
-
        if (is_monitor()) {
                /* monitor bus does not get a panner, but if (re)created
                   via XML, it will already have one by the time we
@@ -2393,22 +2390,6 @@ Route::set_state (const XMLNode& node, int version)
                        } else {
                                warning << string_compose (_("Pannable state found for route (%1) without a panner!"), name()) << endmsg;
                        }
-               }  else if (child->name() == Controllable::xml_node_name) {
-                       if ((prop = child->property (X_("name"))) == 0) {
-                               continue;
-                       }
-
-                       if (prop->value() == _gain_control->name()) {
-                               _gain_control->set_state (*child, version);
-                       } else if (prop->value() == _solo_control->name()) {
-                               _solo_control->set_state (*child, version);
-                       } else if (prop->value() == _solo_safe_control->name()) {
-                               _solo_safe_control->set_state (*child, version);
-                       } else if (prop->value() == _solo_isolate_control->name()) {
-                               _solo_isolate_control->set_state (*child, version);
-                       } else if (prop->value() == _solo_control->name()) {
-                               _mute_control->set_state (*child, version);
-                       }
                } else if (child->name() == Slavable::xml_node_name) {
                        Slavable::set_state (*child, version);
                }
@@ -2466,13 +2447,24 @@ Route::set_state (const XMLNode& node, int version)
                        XMLNode *cmt = *(child->children().begin());
                        _comment = cmt->content();
 
-               } else if (child->name() == Controllable::xml_node_name && (prop = child->property("name")) != 0) {
-                       if (prop->value() == "solo") {
+               }  else if (child->name() == Controllable::xml_node_name) {
+                       if ((prop = child->property (X_("name"))) == 0) {
+                               continue;
+                       }
+
+                       if (prop->value() == _gain_control->name()) {
+                               _gain_control->set_state (*child, version);
+                       } else if (prop->value() == _solo_control->name()) {
                                _solo_control->set_state (*child, version);
-                       } else if (prop->value() == "mute") {
+                       } else if (prop->value() == _solo_safe_control->name()) {
+                               _solo_safe_control->set_state (*child, version);
+                       } else if (prop->value() == _solo_isolate_control->name()) {
+                               _solo_isolate_control->set_state (*child, version);
+                       } else if (prop->value() == _solo_control->name()) {
                                _mute_control->set_state (*child, version);
+                       } else if (prop->value() == _phase_control->name()) {
+                               _phase_control->set_state (*child, version);
                        }
-
                } else if (child->name() == MuteMaster::xml_node_name) {
                        _mute_master->set_state (*child, version);
 
@@ -2506,10 +2498,6 @@ Route::set_state_2X (const XMLNode& node, int version)
 
        Stripable::set_state (node, version);
 
-       if (is_master() || is_monitor() || is_auditioner()) {
-               _mute_master->set_solo_ignore (true);
-       }
-
        if ((prop = node.property (X_("denormal-protection"))) != 0) {
                set_denormal_protection (string_is_affirmative (prop->value()));
        }
@@ -3172,6 +3160,11 @@ Route::direct_feeds_according_to_reality (boost::shared_ptr<Route> other, bool*
 
                if (iop != 0) {
                        boost::shared_ptr<const IO> iop_out = iop->output();
+                       if (other.get() == this && iop_out && iop->input() && iop_out->connected_to (iop->input())) {
+                               // TODO this needs a delaylines in the Insert to align connections (!)
+                               DEBUG_TRACE (DEBUG::Graph,  string_compose ("\tIOP %1 does feed its own return (%2)\n", iop->name(), other->name()));
+                               continue;
+                       }
                        if ((iop_out && other->all_inputs().fed_by (iop_out)) || iop->feeds (other)) {
                                DEBUG_TRACE (DEBUG::Graph,  string_compose ("\tIOP %1 does feed %2\n", iop->name(), other->name()));
                                if (via_send_only) {
@@ -3390,6 +3383,22 @@ Route::pans_required () const
        return max (n_inputs ().n_audio(), processor_max_streams.n_audio());
 }
 
+void
+Route::flush_processor_buffers_locked (framecnt_t nframes)
+{
+       for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+               boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
+               if (d) {
+                       d->flush_buffers (nframes);
+               } else {
+                       boost::shared_ptr<PortInsert> p = boost::dynamic_pointer_cast<PortInsert> (*i);
+                       if (p) {
+                               p->flush_buffers (nframes);
+                       }
+               }
+       }
+}
+
 int
 Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool session_state_changing)
 {
@@ -3435,12 +3444,8 @@ Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame,
        _trim->apply_gain_automation (false);
        passthru (bufs, start_frame, end_frame, nframes, 0);
 
-       for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
-               boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
-               if (d) {
-                       d->flush_buffers (nframes);
-               }
-       }
+       flush_processor_buffers_locked (nframes);
+
        return 0;
 }
 
@@ -3479,12 +3484,8 @@ Route::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, in
 
        passthru (bufs, start_frame, end_frame, nframes, declick);
 
-       for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
-               boost::shared_ptr<Delivery> d = boost::dynamic_pointer_cast<Delivery> (*i);
-               if (d) {
-                       d->flush_buffers (nframes);
-               }
-       }
+       flush_processor_buffers_locked (nframes);
+
        return 0;
 }
 
@@ -3492,6 +3493,7 @@ int
 Route::silent_roll (pframes_t nframes, framepos_t /*start_frame*/, framepos_t /*end_frame*/, bool& /* need_butler */)
 {
        silence (nframes);
+       flush_processor_buffers_locked (nframes);
        return 0;
 }
 
@@ -3715,7 +3717,9 @@ Route::add_export_point()
                Glib::Threads::Mutex::Lock lx (AudioEngine::instance()->process_lock ());
                Glib::Threads::RWLock::WriterLock lw (_processor_lock);
 
-               _capturing_processor.reset (new CapturingProcessor (_session));
+               // this aligns all tracks; but not tracks + busses
+               assert (_session.worst_track_latency () >= _initial_delay);
+               _capturing_processor.reset (new CapturingProcessor (_session, _session.worst_track_latency () - _initial_delay));
                _capturing_processor->activate ();
 
                configure_processors_unlocked (0, &lw);
@@ -4493,10 +4497,17 @@ Route::setup_invisible_processors ()
                new_processors.insert (amp, _monitor_control);
        }
 
+       /* TRIM CONTROL */
+
+       if (_trim && _trim->active()) {
+               assert (!_trim->display_to_user ());
+               new_processors.push_front (_trim);
+       }
+
        /* INTERNAL RETURN */
 
-       /* doing this here means that any monitor control will come just after
-          the return.
+       /* doing this here means that any monitor control will come after
+          the return and trim.
        */
 
        if (_intreturn) {
@@ -4504,10 +4515,6 @@ Route::setup_invisible_processors ()
                new_processors.push_front (_intreturn);
        }
 
-       if (_trim && _trim->active()) {
-               assert (!_trim->display_to_user ());
-               new_processors.push_front (_trim);
-       }
        /* EXPORT PROCESSOR */
 
        if (_capturing_processor) {
@@ -5247,7 +5254,7 @@ Route::muted_by_others_soloing () const
                return false;
        }
 
-       return _session.soloing() && !_solo_control->soloed() && !_solo_isolate_control->solo_isolated();
+       return  _session.soloing() && !_solo_control->soloed() && !_solo_isolate_control->solo_isolated();
 }
 
 void