LTC encoder: clear user-bits
[ardour.git] / libs / ardour / route.cc
index 6f68f172a7c94d735b019656d94185f3b8b63216..8546c3ce76b9a18ecff7f8f28fbf45f63c64ad27 100644 (file)
@@ -26,6 +26,8 @@
 #include <cassert>
 #include <algorithm>
 
+#include <boost/algorithm/string.hpp>
+
 #include "pbd/xml++.h"
 #include "pbd/enumwriter.h"
 #include "pbd/memento_command.h"
 #include "pbd/convert.h"
 #include "pbd/boost_debug.h"
 
-#include "evoral/Curve.hpp"
-
 #include "ardour/amp.h"
-#include "ardour/audio_port.h"
+#include "ardour/audio_buffer.h"
 #include "ardour/audioengine.h"
 #include "ardour/buffer.h"
 #include "ardour/buffer_set.h"
-#include "ardour/configuration.h"
-#include "ardour/cycle_timer.h"
+#include "ardour/capturing_processor.h"
 #include "ardour/debug.h"
 #include "ardour/delivery.h"
-#include "ardour/dB.h"
-#include "ardour/internal_send.h"
 #include "ardour/internal_return.h"
-#include "ardour/ladspa_plugin.h"
+#include "ardour/internal_send.h"
 #include "ardour/meter.h"
-#include "ardour/mix.h"
 #include "ardour/monitor_processor.h"
 #include "ardour/pannable.h"
-#include "ardour/panner.h"
 #include "ardour/panner_shell.h"
 #include "ardour/plugin_insert.h"
 #include "ardour/port.h"
 #include "ardour/port_insert.h"
 #include "ardour/processor.h"
-#include "ardour/profile.h"
 #include "ardour/route.h"
 #include "ardour/route_group.h"
 #include "ardour/send.h"
 #include "ardour/session.h"
-#include "ardour/timestamps.h"
-#include "ardour/utils.h"
 #include "ardour/unknown_processor.h"
-#include "ardour/capturing_processor.h"
+#include "ardour/utils.h"
 
 #include "i18n.h"
 
@@ -74,8 +66,7 @@ using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
-uint32_t Route::order_key_cnt = 0;
-PBD::Signal1<void,string const&> Route::SyncOrderKeys;
+PBD::Signal1<void,RouteSortOrderKey> Route::SyncOrderKeys;
 PBD::Signal0<void> Route::RemoteControlIDChange;
 
 Route::Route (Session& sess, string name, Flag flg, DataType default_type)
@@ -107,14 +98,6 @@ Route::Route (Session& sess, string name, Flag flg, DataType default_type)
        , _last_custom_meter_was_at_end (false)
 {
        processor_max_streams.reset();
-       order_keys[N_("signal")] = order_key_cnt++;
-
-       if (is_master()) {
-               set_remote_control_id (MasterBusRemoteControlID);
-       } else if (is_monitor()) {
-               set_remote_control_id (MonitorBusRemoteControlID);
-       }
-               
 }
 
 int
@@ -185,7 +168,7 @@ Route::init ()
 
        {
                /* run a configure so that the invisible processors get set up */
-               Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+               Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
                configure_processors (0);
        }
 
@@ -205,7 +188,7 @@ Route::~Route ()
           be half-destroyed by now
        */
 
-       Glib::RWLock::WriterLock lm (_processor_lock);
+       Glib::Threads::RWLock::WriterLock lm (_processor_lock);
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                (*i)->drop_references ();
        }
@@ -216,6 +199,15 @@ Route::~Route ()
 void
 Route::set_remote_control_id (uint32_t id, bool notify_class_listeners)
 {
+       if (Config->get_remote_model() != UserOrdered) {
+               return;
+       }
+       
+       if (id < 1) {
+               error << _("Remote Control ID's start at one, not zero") << endmsg;
+               return;
+       }
+
        /* force IDs for master/monitor busses and prevent 
           any other route from accidentally getting these IDs
           (i.e. legacy sessions)
@@ -236,9 +228,10 @@ Route::set_remote_control_id (uint32_t id, bool notify_class_listeners)
                id += MonitorBusRemoteControlID;
        }
 
-       if (id != _remote_control_id) {
+       if (id != remote_control_id()) {
                _remote_control_id = id;
                RemoteControlIDChanged ();
+
                if (notify_class_listeners) {
                        RemoteControlIDChange ();
                }
@@ -248,88 +241,101 @@ Route::set_remote_control_id (uint32_t id, bool notify_class_listeners)
 uint32_t
 Route::remote_control_id() const
 {
+       if (is_master()) {
+               return MasterBusRemoteControlID;
+       } 
+
+       if (is_monitor()) {
+               return MonitorBusRemoteControlID;
+       }
+
        return _remote_control_id;
 }
 
-int32_t
-Route::order_key (std::string const & name) const
+bool
+Route::has_order_key (RouteSortOrderKey key) const
 {
-       OrderKeys::const_iterator i = order_keys.find (name);
+       return (order_keys.find (key) != order_keys.end());
+}
+
+uint32_t
+Route::order_key (RouteSortOrderKey key) const
+{
+       OrderKeys::const_iterator i = order_keys.find (key);
+
        if (i == order_keys.end()) {
-               return -1;
+               return 0;
        }
 
        return i->second;
 }
 
 void
-Route::set_order_key (std::string const & name, int32_t n)
+Route::sync_order_keys (RouteSortOrderKey base)
 {
-       bool changed = false;
+       /* this is called after changes to 1 or more route order keys have been
+        * made, and we want to sync up.
+        */
 
-       /* This method looks more complicated than it should, but
-          it's important that we don't emit order_key_changed unless
-          it actually has, as expensive things happen on receipt of that
-          signal.
-       */
+       OrderKeys::iterator i = order_keys.find (base);
 
-       if (order_keys.find(name) == order_keys.end() || order_keys[name] != n) {
-               order_keys[name] = n;
-               changed = true;
+       if (i == order_keys.end()) {
+               return;
        }
 
-       if (Config->get_sync_all_route_ordering()) {
-               for (OrderKeys::iterator x = order_keys.begin(); x != order_keys.end(); ++x) {
-                       if (x->second != n) {
-                               x->second = n;
-                               changed = true;
-                       }
-               }
-       }
+       for (OrderKeys::iterator k = order_keys.begin(); k != order_keys.end(); ++k) {
 
-       if (changed) {
-               order_key_changed (); /* EMIT SIGNAL */
-               _session.set_dirty ();
+               if (k->first != base) {
+                       DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("%1 set key for %2 to %3 from %4\n",
+                                                                      name(),
+                                                                      enum_2_string (k->first),
+                                                                      i->second,
+                                                                      enum_2_string (base)));
+                                                                      
+                       k->second = i->second;
+               }
        }
 }
 
-/** Set all order keys to be the same as that for `base', if such a key
- *  exists in this route.
- *  @param base Base key.
- */
 void
-Route::sync_order_keys (std::string const & base)
+Route::set_remote_control_id_from_order_key (RouteSortOrderKey key, uint32_t rid)
 {
-       if (order_keys.empty()) {
+       if (is_master() || is_monitor() || is_hidden()) {
+               /* hard-coded remote IDs, or no remote ID */
                return;
        }
 
-       OrderKeys::iterator i;
-       int32_t key;
-
-       if ((i = order_keys.find (base)) == order_keys.end()) {
-               /* key doesn't exist, use the first existing key (during session initialization) */
-               i = order_keys.begin();
-               key = i->second;
-               ++i;
-       } else {
-               /* key exists - use it and reset all others (actually, itself included) */
-               key = i->second;
-               i = order_keys.begin();
+       if (_remote_control_id != rid) {
+               DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("%1: set edit-based RID to %2\n", name(), rid));
+               _remote_control_id = rid;
+               RemoteControlIDChanged (); /* EMIT SIGNAL (per-route) */
        }
 
-       bool changed = false;
+       /* don't emit the class-level RID signal RemoteControlIDChange here,
+          leave that to the entity that changed the order key, so that we
+          don't get lots of emissions for no good reasons (e.g. when changing
+          all route order keys).
 
-       for (; i != order_keys.end(); ++i) {
-               if (i->second != key) {
-                       i->second = key;
-                       changed = true;
-               }
-       }
+          See Session::sync_remote_id_from_order_keys() for the (primary|only)
+          spot where that is emitted.
+       */
+}
 
-       if (changed) {
-               order_key_changed (); /* EMIT SIGNAL */
+void
+Route::set_order_key (RouteSortOrderKey key, uint32_t n)
+{
+       OrderKeys::iterator i = order_keys.find (key);
+
+       if (i != order_keys.end() && i->second == n) {
+               return;
        }
+
+       order_keys[key] = n;
+
+       DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("%1 order key %2 set to %3\n",
+                                                      name(), enum_2_string (key), order_key (key)));
+
+       _session.set_dirty ();
 }
 
 string
@@ -433,6 +439,7 @@ Route::process_output_buffers (BufferSet& bufs,
 
        /* figure out if we're going to use gain automation */
        if (gain_automation_ok) {
+               _amp->set_gain_automation_buffer (_session.gain_automation_buffer ());
                _amp->setup_gain_automation (start_frame, end_frame, nframes);
        } else {
                _amp->apply_gain_automation (false);
@@ -518,19 +525,17 @@ Route::process_output_buffers (BufferSet& bufs,
                        continue;
                }
 
-               if (Config->get_plugins_stop_with_transport() && _session.transport_speed() == 0 && boost::dynamic_pointer_cast<PluginInsert> (*i)) {
-                       /* don't run plugins with the transport stopped, if configured this way */
-                       continue;
-               }
-               
 #ifndef NDEBUG
                /* if it has any inputs, make sure they match */
                if (boost::dynamic_pointer_cast<UnknownProcessor> (*i) == 0 && (*i)->input_streams() != ChanCount::ZERO) {
                        if (bufs.count() != (*i)->input_streams()) {
-                               cerr << _name << " bufs = " << bufs.count()
-                                    << " input for " << (*i)->name() << " = " << (*i)->input_streams()
-                                    << endl;
-                               abort ();
+                               DEBUG_TRACE (
+                                       DEBUG::Processors, string_compose (
+                                               "%1 bufs = %2 input for %3 = %4\n",
+                                               _name, bufs.count(), (*i)->name(), (*i)->input_streams()
+                                               )
+                                       );
+                               continue;
                        }
                }
 #endif
@@ -880,7 +885,7 @@ dump_processors(const string& name, const list<boost::shared_ptr<Processor> >& p
 boost::shared_ptr<Processor>
 Route::before_processor_for_placement (Placement p)
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
 
        ProcessorList::iterator loc;
        
@@ -905,7 +910,7 @@ Route::before_processor_for_index (int index)
                return boost::shared_ptr<Processor> ();
        }
 
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
        
        ProcessorList::iterator i = _processors.begin ();
        int j = 0;
@@ -958,7 +963,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, boost::shared_ptr<
        }
 
        {
-               Glib::RWLock::WriterLock lm (_processor_lock);
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
                ProcessorState pstate (this);
 
                boost::shared_ptr<PluginInsert> pi;
@@ -998,7 +1003,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, boost::shared_ptr<
                // configure redirect ports properly, etc.
 
                {
-                       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
 
                        if (configure_processors_unlocked (err)) {
                                pstate.restore ();
@@ -1016,7 +1021,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, boost::shared_ptr<
 
                }
 
-               if (activation_allowed) {
+               if (activation_allowed && !_session.get_disable_all_loaded_plugins()) {
                        processor->activate ();
                }
 
@@ -1025,6 +1030,7 @@ Route::add_processor (boost::shared_ptr<Processor> processor, boost::shared_ptr<
                _output->set_user_latency (0);
        }
 
+       reset_instrument_info ();
        processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
        set_processor_positions ();
 
@@ -1064,7 +1070,7 @@ Route::add_processor_from_xml_2X (const XMLNode& node, int version)
 
                                if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
                                                prop->value() == "lv2" ||
-                                               prop->value() == "vst" ||
+                                               prop->value() == "windows-vst" ||
                                                prop->value() == "lxvst" ||
                                                prop->value() == "audiounit") {
 
@@ -1126,7 +1132,7 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
        }
 
        {
-               Glib::RWLock::WriterLock lm (_processor_lock);
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
                ProcessorState pstate (this);
 
                for (ProcessorList::const_iterator i = others.begin(); i != others.end(); ++i) {
@@ -1148,7 +1154,7 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
                        }
 
                        {
-                               Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                               Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
                                if (configure_processors_unlocked (err)) {
                                        pstate.restore ();
                                        configure_processors_unlocked (0); // it worked before we tried to add it ...
@@ -1173,6 +1179,7 @@ Route::add_processors (const ProcessorList& others, boost::shared_ptr<Processor>
                _output->set_user_latency (0);
        }
 
+       reset_instrument_info ();
        processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
        set_processor_positions ();
 
@@ -1198,7 +1205,7 @@ Route::placement_range(Placement p, ProcessorList::iterator& start, ProcessorLis
 void
 Route::disable_processors (Placement p)
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
 
        ProcessorList::iterator start, end;
        placement_range(p, start, end);
@@ -1215,7 +1222,7 @@ Route::disable_processors (Placement p)
 void
 Route::disable_processors ()
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
 
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                (*i)->deactivate ();
@@ -1230,7 +1237,7 @@ Route::disable_processors ()
 void
 Route::disable_plugins (Placement p)
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
 
        ProcessorList::iterator start, end;
        placement_range(p, start, end);
@@ -1249,7 +1256,7 @@ Route::disable_plugins (Placement p)
 void
 Route::disable_plugins ()
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
 
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                if (boost::dynamic_pointer_cast<PluginInsert> (*i)) {
@@ -1264,7 +1271,7 @@ Route::disable_plugins ()
 void
 Route::ab_plugins (bool forward)
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
 
        if (forward) {
 
@@ -1323,7 +1330,7 @@ Route::clear_processors (Placement p)
        }
 
        {
-               Glib::RWLock::WriterLock lm (_processor_lock);
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
                ProcessorList new_list;
                ProcessorStreams err;
                bool seen_amp = false;
@@ -1369,7 +1376,7 @@ Route::clear_processors (Placement p)
                _processors = new_list;
 
                {
-                       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
                        configure_processors_unlocked (&err); // this can't fail
                }
        }
@@ -1379,6 +1386,8 @@ Route::clear_processors (Placement p)
        processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
        set_processor_positions ();
 
+       reset_instrument_info ();
+
        if (!already_deleting) {
                _session.clear_deletion_in_progress();
        }
@@ -1387,6 +1396,11 @@ Route::clear_processors (Placement p)
 int
 Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStreams* err, bool need_process_lock)
 {
+       // TODO once the export point can be configured properly, do something smarter here
+       if (processor == _capturing_processor) {
+               _capturing_processor.reset();
+       }
+
        /* these can never be removed */
 
        if (processor == _amp || processor == _meter || processor == _main_outs) {
@@ -1400,7 +1414,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
        processor_max_streams.reset();
 
        {
-               Glib::RWLock::WriterLock lm (_processor_lock);
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
                ProcessorState pstate (this);
 
                ProcessorList::iterator i;
@@ -1421,12 +1435,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
                                boost::shared_ptr<IOProcessor> iop;
 
                                if ((iop = boost::dynamic_pointer_cast<IOProcessor> (*i)) != 0) {
-                                       if (iop->input()) {
-                                               iop->input()->disconnect (this);
-                                       }
-                                       if (iop->output()) {
-                                               iop->output()->disconnect (this);
-                                       }
+                                       iop->disconnect ();
                                }
 
                                i = _processors.erase (i);
@@ -1446,7 +1455,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
                } 
 
                if (need_process_lock) {
-                       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
 
                        if (configure_processors_unlocked (err)) {
                                pstate.restore ();
@@ -1477,6 +1486,7 @@ Route::remove_processor (boost::shared_ptr<Processor> processor, ProcessorStream
                }
        }
 
+       reset_instrument_info ();
        processor->drop_references ();
        processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
        set_processor_positions ();
@@ -1496,7 +1506,7 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
        processor_max_streams.reset();
 
        {
-               Glib::RWLock::WriterLock lm (_processor_lock);
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
                ProcessorState pstate (this);
 
                ProcessorList::iterator i;
@@ -1543,7 +1553,7 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
                _output->set_user_latency (0);
 
                {
-                       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
 
                        if (configure_processors_unlocked (err)) {
                                pstate.restore ();
@@ -1573,12 +1583,22 @@ Route::remove_processors (const ProcessorList& to_be_deleted, ProcessorStreams*
                (*i)->drop_references ();
        }
 
+       reset_instrument_info ();
        processors_changed (RouteProcessorChange ()); /* EMIT SIGNAL */
        set_processor_positions ();
 
        return 0;
 }
 
+void
+Route::reset_instrument_info ()
+{
+       boost::shared_ptr<Processor> instr = the_instrument();
+       if (instr) {
+               _instrument_info.set_internal_instrument (instr);
+       }
+}
+
 /** Caller must hold process lock */
 int
 Route::configure_processors (ProcessorStreams* err)
@@ -1586,7 +1606,7 @@ Route::configure_processors (ProcessorStreams* err)
        assert (!AudioEngine::instance()->process_lock().trylock());
 
        if (!_in_configure_processors) {
-               Glib::RWLock::WriterLock lm (_processor_lock);
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
                return configure_processors_unlocked (err);
        }
 
@@ -1602,7 +1622,7 @@ Route::input_streams () const
 list<pair<ChanCount, ChanCount> >
 Route::try_configure_processors (ChanCount in, ProcessorStreams* err)
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
 
        return try_configure_processors_unlocked (in, err);
 }
@@ -1707,7 +1727,7 @@ Route::configure_processors_unlocked (ProcessorStreams* err)
 void
 Route::all_visible_processors_active (bool state)
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
 
        if (_processors.empty()) {
                return;
@@ -1738,7 +1758,7 @@ Route::reorder_processors (const ProcessorList& new_order, ProcessorStreams* err
        */
 
        {
-               Glib::RWLock::WriterLock lm (_processor_lock);
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
                ProcessorState pstate (this);
 
                ProcessorList::iterator oiter;
@@ -1800,7 +1820,7 @@ Route::reorder_processors (const ProcessorList& new_order, ProcessorStreams* err
                maybe_note_meter_position ();
 
                {
-                       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
 
                        if (configure_processors_unlocked (err)) {
                                pstate.restore ();
@@ -1858,9 +1878,9 @@ Route::state(bool full_state)
        OrderKeys::iterator x = order_keys.begin();
 
        while (x != order_keys.end()) {
-               order_string += string ((*x).first);
+               order_string += enum_2_string ((*x).first);
                order_string += '=';
-               snprintf (buf, sizeof(buf), "%ld", (*x).second);
+               snprintf (buf, sizeof(buf), "%" PRId32, (*x).second);
                order_string += buf;
 
                ++x;
@@ -2007,7 +2027,6 @@ Route::set_state (const XMLNode& node, int version)
                        processor_state.add_child_copy (*child);
                }
 
-
                if (child->name() == X_("Pannable")) {
                        if (_pannable) {
                                _pannable->set_state (*child, version);
@@ -2027,6 +2046,9 @@ Route::set_state (const XMLNode& node, int version)
 
        set_processor_state (processor_state);
 
+       // this looks up the internal instrument in processors
+       reset_instrument_info();
+
        if ((prop = node.property ("self-solo")) != 0) {
                set_self_solo (string_is_affirmative (prop->value()));
        }
@@ -2080,7 +2102,18 @@ Route::set_state (const XMLNode& node, int version)
                                        error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
                                              << endmsg;
                                } else {
-                                       set_order_key (remaining.substr (0, equal), n);
+                                       string keyname = remaining.substr (0, equal);
+                                       RouteSortOrderKey sk;
+
+                                       if (keyname == "signal") {
+                                               sk = MixerSort;
+                                       } else if (keyname == "editor") {
+                                               sk = EditorSort;
+                                       } else {
+                                               sk = (RouteSortOrderKey) string_2_enum (remaining.substr (0, equal), sk);
+                                       }
+
+                                       set_order_key (sk, n);
                                }
                        }
 
@@ -2096,7 +2129,7 @@ Route::set_state (const XMLNode& node, int version)
 
        if ((prop = node.property (X_("processor-after-last-custom-meter"))) != 0) {
                PBD::ID id (prop->value ());
-               Glib::RWLock::ReaderLock lm (_processor_lock);
+               Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
                ProcessorList::const_iterator i = _processors.begin ();
                while (i != _processors.end() && (*i)->id() != id) {
                        ++i;
@@ -2125,6 +2158,8 @@ Route::set_state (const XMLNode& node, int version)
                } else if (child->name() == Controllable::xml_node_name && (prop = child->property("name")) != 0) {
                        if (prop->value() == "solo") {
                                _solo_control->set_state (*child, version);
+                       } else if (prop->value() == "mute") {
+                               _mute_control->set_state (*child, version);
                        }
 
                } else if (child->name() == X_("RemoteControl")) {
@@ -2162,7 +2197,9 @@ Route::set_state_2X (const XMLNode& node, int version)
        }
 
        if ((prop = node.property (X_("flags"))) != 0) {
-               _flags = Flag (string_2_enum (prop->value(), _flags));
+               string f = prop->value ();
+               boost::replace_all (f, "ControlOut", "MonitorOut");
+               _flags = Flag (string_2_enum (f, _flags));
        } else {
                _flags = Flag (0);
        }
@@ -2272,7 +2309,18 @@ Route::set_state_2X (const XMLNode& node, int version)
                                        error << string_compose (_("badly formed order key string in state file! [%1] ... ignored."), remaining)
                                                << endmsg;
                                } else {
-                                       set_order_key (remaining.substr (0, equal), n);
+                                       string keyname = remaining.substr (0, equal);
+                                       RouteSortOrderKey sk;
+
+                                       if (keyname == "signal") {
+                                               sk = MixerSort;
+                                       } else if (keyname == "editor") {
+                                               sk = EditorSort;
+                                       } else {
+                                               sk = (RouteSortOrderKey) string_2_enum (remaining.substr (0, equal), sk);
+                                       }
+
+                                       set_order_key (sk, n);
                                }
                        }
 
@@ -2446,7 +2494,8 @@ Route::set_processor_state (const XMLNode& node)
                        }
                        _monitor_control->set_state (**niter, Stateful::current_state_version);
                } else if (prop->value() == "capture") {
-                       _capturing_processor.reset (new CapturingProcessor (_session));
+                       /* CapturingProcessor should never be restored, it's always
+                          added explicitly when needed */
                } else {
                        ProcessorList::iterator o;
 
@@ -2471,7 +2520,7 @@ Route::set_processor_state (const XMLNode& node)
 
                                } else if (prop->value() == "ladspa" || prop->value() == "Ladspa" ||
                                           prop->value() == "lv2" ||
-                                          prop->value() == "vst" ||
+                                          prop->value() == "windows-vst" ||
                                           prop->value() == "lxvst" ||
                                           prop->value() == "audiounit") {
 
@@ -2514,11 +2563,11 @@ Route::set_processor_state (const XMLNode& node)
        }
 
        {
-               Glib::RWLock::WriterLock lm (_processor_lock);
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
                _processors = new_order;
 
                if (must_configure) {
-                       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
                        configure_processors_unlocked (0);
                }
 
@@ -2537,6 +2586,7 @@ Route::set_processor_state (const XMLNode& node)
                }
        }
 
+       reset_instrument_info ();
        processors_changed (RouteProcessorChange ());
        set_processor_positions ();
 }
@@ -2551,7 +2601,7 @@ Route::curve_reallocate ()
 void
 Route::silence (framecnt_t nframes)
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
        if (!lm.locked()) {
                return;
        }
@@ -2597,7 +2647,7 @@ Route::add_internal_return ()
 void
 Route::add_send_to_internal_return (InternalSend* send)
 {
-       Glib::RWLock::ReaderLock rm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock rm (_processor_lock);
 
        for (ProcessorList::const_iterator x = _processors.begin(); x != _processors.end(); ++x) {
                boost::shared_ptr<InternalReturn> d = boost::dynamic_pointer_cast<InternalReturn>(*x);
@@ -2611,8 +2661,7 @@ Route::add_send_to_internal_return (InternalSend* send)
 void
 Route::remove_send_from_internal_return (InternalSend* send)
 {
-       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
-       Glib::RWLock::ReaderLock rm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock rm (_processor_lock);
 
        for (ProcessorList::const_iterator x = _processors.begin(); x != _processors.end(); ++x) {
                boost::shared_ptr<InternalReturn> d = boost::dynamic_pointer_cast<InternalReturn>(*x);
@@ -2652,7 +2701,7 @@ Route::add_aux_send (boost::shared_ptr<Route> route, boost::shared_ptr<Processor
        assert (route != _session.monitor_out ());
 
        {
-               Glib::RWLock::ReaderLock rm (_processor_lock);
+               Glib::Threads::RWLock::ReaderLock rm (_processor_lock);
 
                for (ProcessorList::iterator x = _processors.begin(); x != _processors.end(); ++x) {
 
@@ -2670,7 +2719,7 @@ Route::add_aux_send (boost::shared_ptr<Route> route, boost::shared_ptr<Processor
                boost::shared_ptr<InternalSend> listener;
 
                {
-                       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
                        listener.reset (new InternalSend (_session, _pannable, _mute_master, route, Delivery::Aux));
                }
 
@@ -2690,7 +2739,7 @@ Route::remove_aux_or_listen (boost::shared_ptr<Route> route)
        ProcessorList::iterator tmp;
 
        {
-               Glib::RWLock::ReaderLock rl(_processor_lock);
+               Glib::Threads::RWLock::ReaderLock rl(_processor_lock);
 
                /* have to do this early because otherwise processor reconfig
                 * will put _monitor_send back in the list
@@ -2826,11 +2875,7 @@ Route::nonrealtime_handle_transport_stopped (bool /*abort_ignored*/, bool did_lo
        framepos_t now = _session.transport_frame();
 
        {
-               Glib::RWLock::ReaderLock lm (_processor_lock);
-
-               if (!did_locate) {
-                       automation_snapshot (now, true);
-               }
+               Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
 
                Automatable::transport_stopped (now);
 
@@ -2917,7 +2962,7 @@ Route::pans_required () const
 int
 Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, bool session_state_changing)
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
        if (!lm.locked()) {
                return 0;
        }
@@ -2954,13 +2999,11 @@ Route::no_roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame,
 int
 Route::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, int declick, bool& /* need_butler */)
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock, Glib::TRY_LOCK);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
        if (!lm.locked()) {
                return 0;
        }
 
-       automation_snapshot (_session.transport_frame(), false);
-
        if (n_outputs().n_total() == 0) {
                return 0;
        }
@@ -2970,7 +3013,7 @@ Route::roll (pframes_t nframes, framepos_t start_frame, framepos_t end_frame, in
                return 0;
        }
 
-       framecnt_t unused = 0;
+       framepos_t unused = 0;
 
        if ((nframes = check_initial_delay (nframes, unused)) == 0) {
                return 0;
@@ -2997,7 +3040,7 @@ Route::flush_processors ()
           this is called from the RT audio thread.
        */
 
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
 
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                (*i)->flush ();
@@ -3016,7 +3059,7 @@ Route::set_meter_point (MeterPoint p, bool force)
        bool meter_was_visible_to_user = _meter->display_to_user ();
 
        {
-               Glib::RWLock::WriterLock lm (_processor_lock);
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
 
                maybe_note_meter_position ();
 
@@ -3083,11 +3126,11 @@ void
 Route::listen_position_changed ()
 {
        {
-               Glib::RWLock::WriterLock lm (_processor_lock);
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
                ProcessorState pstate (this);
 
                {
-                       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
 
                        if (configure_processors_unlocked (0)) {
                                pstate.restore ();
@@ -3110,7 +3153,7 @@ Route::add_export_point()
                _capturing_processor->activate ();
 
                {
-                       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
                        configure_processors (0);
                }
 
@@ -3172,18 +3215,6 @@ Route::set_latency_compensation (framecnt_t longest_session_latency)
        }
 }
 
-void
-Route::automation_snapshot (framepos_t now, bool force)
-{
-       if (_pannable) {
-               _pannable->automation_snapshot (now, force);
-       }
-
-       for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
-               (*i)->automation_snapshot (now, force);
-       }
-}
-
 Route::SoloControllable::SoloControllable (std::string name, boost::shared_ptr<Route> r)
        : AutomationControl (r->session(), Evoral::Parameter (SoloAutomation),
                             boost::shared_ptr<AutomationList>(), name)
@@ -3282,19 +3313,20 @@ Route::protect_automation ()
                (*i)->protect_automation();
 }
 
+/** @param declick 1 to set a pending declick fade-in,
+ *                -1 to set a pending declick fade-out
+ */
 void
 Route::set_pending_declick (int declick)
 {
        if (_declickable) {
-               /* this call is not allowed to turn off a pending declick unless "force" is true */
+               /* this call is not allowed to turn off a pending declick */
                if (declick) {
                        _pending_declick = declick;
                }
-               // cerr << _name << ": after setting to " << declick << " pending declick = " << _pending_declick << endl;
        } else {
                _pending_declick = 0;
        }
-
 }
 
 /** Shift automation forwards from a particular place, thereby inserting time.
@@ -3335,7 +3367,7 @@ Route::shift (framepos_t pos, framecnt_t frames)
 
        /* redirect automation */
        {
-               Glib::RWLock::ReaderLock lm (_processor_lock);
+               Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
                for (ProcessorList::iterator i = _processors.begin (); i != _processors.end (); ++i) {
 
                        set<Evoral::Parameter> parameters = (*i)->what_can_be_automated();
@@ -3435,7 +3467,7 @@ Route::set_name_in_state (XMLNode& node, string const & name)
 boost::shared_ptr<Send>
 Route::internal_send_for (boost::shared_ptr<const Route> target) const
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
 
        for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
                boost::shared_ptr<InternalSend> send;
@@ -3513,13 +3545,14 @@ Route::set_active (bool yn, void* src)
                _input->set_active (yn);
                _output->set_active (yn);
                active_changed (); // EMIT SIGNAL
+               _session.set_dirty ();
        }
 }
 
 void
 Route::meter ()
 {
-       Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
+       Glib::Threads::RWLock::ReaderLock rm (_processor_lock, Glib::Threads::TRY_LOCK);
 
        assert (_meter);
 
@@ -3574,7 +3607,7 @@ Route::get_control (const Evoral::Parameter& param)
 
                /* maybe one of our processors does or ... */
 
-               Glib::RWLock::ReaderLock rm (_processor_lock, Glib::TRY_LOCK);
+               Glib::Threads::RWLock::ReaderLock rm (_processor_lock, Glib::Threads::TRY_LOCK);
                for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
                        if ((c = boost::dynamic_pointer_cast<AutomationControl>((*i)->control (param))) != 0) {
                                break;
@@ -3596,7 +3629,7 @@ Route::get_control (const Evoral::Parameter& param)
 boost::shared_ptr<Processor>
 Route::nth_plugin (uint32_t n)
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
        ProcessorList::iterator i;
 
        for (i = _processors.begin(); i != _processors.end(); ++i) {
@@ -3613,7 +3646,7 @@ Route::nth_plugin (uint32_t n)
 boost::shared_ptr<Processor>
 Route::nth_send (uint32_t n)
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
        ProcessorList::iterator i;
 
        for (i = _processors.begin(); i != _processors.end(); ++i) {
@@ -3630,7 +3663,7 @@ Route::nth_send (uint32_t n)
 bool
 Route::has_io_processor_named (const string& name)
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
        ProcessorList::iterator i;
 
        for (i = _processors.begin(); i != _processors.end(); ++i) {
@@ -3654,7 +3687,7 @@ Route::mute_points () const
 void
 Route::set_processor_positions ()
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
 
        bool had_amp = false;
        for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
@@ -3686,7 +3719,7 @@ Route::unknown_processors () const
 {
        list<string> p;
 
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
        for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
                if (boost::dynamic_pointer_cast<UnknownProcessor const> (*i)) {
                        p.push_back ((*i)->name ());
@@ -3811,7 +3844,7 @@ void
 Route::setup_invisible_processors ()
 {
 #ifndef NDEBUG
-       Glib::RWLock::WriterLock lm (_processor_lock, Glib::TRY_LOCK);
+       Glib::Threads::RWLock::WriterLock lm (_processor_lock, Glib::Threads::TRY_LOCK);
        assert (!lm.locked ());
 #endif
 
@@ -3967,8 +4000,8 @@ Route::setup_invisible_processors ()
 void
 Route::unpan ()
 {
-       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
-       Glib::RWLock::ReaderLock lp (_processor_lock);
+       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+       Glib::Threads::RWLock::ReaderLock lp (_processor_lock);
 
        _pannable.reset ();
 
@@ -4012,7 +4045,7 @@ Route::maybe_note_meter_position ()
 boost::shared_ptr<Processor>
 Route::processor_by_id (PBD::ID id) const
 {
-       Glib::RWLock::ReaderLock lm (_processor_lock);
+       Glib::Threads::RWLock::ReaderLock lm (_processor_lock);
        for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
                if ((*i)->id() == id) {
                        return *i;
@@ -4039,3 +4072,51 @@ Route::metering_state () const
 {
        return MeteringRoute;
 }
+
+bool
+Route::has_external_redirects () const
+{
+       for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
+
+               /* ignore inactive processors and obviously ignore the main
+                * outs since everything has them and we don't care.
+                */
+                
+               if ((*i)->active() && (*i) != _main_outs && (*i)->does_routing()) {
+                       return true;;
+               }
+       }
+
+       return false;
+}
+
+boost::shared_ptr<Processor>
+Route::the_instrument () const
+{
+       Glib::Threads::RWLock::WriterLock lm (_processor_lock);
+       for (ProcessorList::const_iterator i = _processors.begin(); i != _processors.end(); ++i) {
+               if (boost::dynamic_pointer_cast<PluginInsert>(*i)) {
+                       if ((*i)->input_streams().n_midi() > 0 &&
+                           (*i)->output_streams().n_audio() > 0) {
+                               return (*i);
+                       }
+               }
+       }
+       return boost::shared_ptr<Processor>();
+}
+
+void
+Route::non_realtime_locate (framepos_t pos)
+{
+       if (_pannable) {
+               _pannable->transport_located (pos);
+       }
+
+       {
+               Glib::Threads::RWLock::WriterLock lm (_processor_lock);
+               
+               for (ProcessorList::iterator i = _processors.begin(); i != _processors.end(); ++i) {
+                       (*i)->transport_located (pos);
+               }
+       }
+}