NOOP, remove trailing tabs/whitespace.
[ardour.git] / libs / ardour / session.cc
index 71ad0bd7058622165619e891d282a41fc501d509..879bd7653960b4c799a4c95b65cf5db880bed412 100644 (file)
@@ -46,6 +46,7 @@
 #include "pbd/search_path.h"
 #include "pbd/stacktrace.h"
 #include "pbd/stl_delete.h"
+#include "pbd/replace_all.h"
 #include "pbd/unwind.h"
 
 #include "ardour/amp.h"
@@ -67,6 +68,9 @@
 #include "ardour/data_type.h"
 #include "ardour/debug.h"
 #include "ardour/directory_names.h"
+#ifdef USE_TRACKS_CODE_FEATURES
+#include "ardour/engine_state_controller.h"
+#endif
 #include "ardour/filename_extensions.h"
 #include "ardour/graph.h"
 #include "ardour/midiport_manager.h"
@@ -78,6 +82,7 @@
 #include "ardour/plugin.h"
 #include "ardour/plugin_insert.h"
 #include "ardour/process_thread.h"
+#include "ardour/profile.h"
 #include "ardour/rc_configuration.h"
 #include "ardour/recent_sessions.h"
 #include "ardour/region.h"
 
 #include "i18n.h"
 
+#include <glibmm/checksum.h>
+
 namespace ARDOUR {
 class MidiSource;
 class Processor;
@@ -113,6 +120,7 @@ using namespace ARDOUR;
 using namespace PBD;
 
 bool Session::_disable_all_loaded_plugins = false;
+bool Session::_bypass_all_loaded_plugins = false;
 
 PBD::Signal1<int,uint32_t> Session::AudioEngineSetupRequired;
 PBD::Signal1<void,std::string> Session::Dialog;
@@ -130,10 +138,17 @@ PBD::Signal0<void> Session::FeedbackDetected;
 PBD::Signal0<void> Session::SuccessfulGraphSort;
 PBD::Signal2<void,std::string,std::string> Session::VersionMismatch;
 
-const framecnt_t Session::bounce_chunk_size = 65536;
+const framecnt_t Session::bounce_chunk_size = 8192;
 static void clean_up_session_event (SessionEvent* ev) { delete ev; }
 const SessionEvent::RTeventCallback Session::rt_cleanup (clean_up_session_event);
 
+// seconds should be added after the region exceeds end marker
+#ifdef USE_TRACKS_CODE_FEATURES
+const uint32_t Session::session_end_shift = 5;
+#else
+const uint32_t Session::session_end_shift = 0;
+#endif
+
 /** @param snapshot_name Snapshot name, without .ardour suffix */
 Session::Session (AudioEngine &eng,
                   const string& fullpath,
@@ -179,6 +194,8 @@ Session::Session (AudioEngine &eng,
        , average_dir (0)
        , have_first_delta_accumulator (false)
        , _slave_state (Stopped)
+       , _mtc_active (false)
+       , _ltc_active (false)
        , post_export_sync (false)
        , post_export_position (0)
        , _exporting (false)
@@ -194,7 +211,7 @@ Session::Session (AudioEngine &eng,
        , loop_changing (false)
        , last_loopend (0)
        , _session_dir (new SessionDirectory (fullpath))
-       , _current_snapshot_name (snapshot_name)          
+       , _current_snapshot_name (snapshot_name)
        , state_tree (0)
        , state_was_pending (false)
        , _state_of_the_state (StateOfTheState(CannotSave|InitialConnecting|Loading))
@@ -243,9 +260,10 @@ Session::Session (AudioEngine &eng,
        , _all_route_group (new RouteGroup (*this, "all"))
        , routes (new RouteList)
        , _adding_routes_in_progress (false)
+       , _reconnecting_routes_in_progress (false)
+       , _route_deletion_in_progress (false)
        , destructive_index (0)
        , _track_number_decimals(1)
-       , solo_update_disabled (false)
        , default_fade_steepness (0)
        , default_fade_msecs (0)
        , _total_free_4k_blocks (0)
@@ -263,11 +281,14 @@ Session::Session (AudioEngine &eng,
        , click_emphasis_length (0)
        , _clicks_cleared (0)
        , _play_range (false)
+       , _range_selection (-1,-1)
+       , _object_selection (-1,-1)
        , main_outs (0)
        , first_file_data_format_reset (true)
        , first_file_header_format_reset (true)
        , have_looped (false)
        , _have_rec_enabled_track (false)
+    , _have_rec_disabled_track (true)
        , _step_editors (0)
        , _suspend_timecode_transmission (0)
        ,  _speakers (new Speakers)
@@ -283,16 +304,22 @@ Session::Session (AudioEngine &eng,
        pthread_cond_init (&_rt_emit_cond, 0);
 
        pre_engine_init (fullpath);
-       
+
        if (_is_new) {
+
+               Stateful::loading_state_version = CURRENT_SESSION_FILE_VERSION;
+
+#ifdef USE_TRACKS_CODE_FEATURES
+               sr = EngineStateController::instance()->get_current_sample_rate();
+#endif
                if (ensure_engine (sr)) {
                        destroy ();
-                       throw failed_constructor ();
+                       throw SessionException (_("Cannot connect to audio/midi engine"));
                }
 
                if (create (mix_template, bus_profile)) {
                        destroy ();
-                       throw failed_constructor ();
+                       throw SessionException (_("Session initialization failed"));
                }
 
                /* if a mix template was provided, then ::create() will
@@ -306,8 +333,11 @@ Session::Session (AudioEngine &eng,
                 * of a template.
                 */
 
-               if (!mix_template.empty() && load_state (_current_snapshot_name)) {
-                       throw failed_constructor ();
+               if (!mix_template.empty()) {
+                       if (load_state (_current_snapshot_name)) {
+                               throw SessionException (_("Failed to load template/snapshot state"));
+                       }
+                       store_recent_templates (mix_template);
                }
 
                /* load default session properties - if any */
@@ -316,9 +346,9 @@ Session::Session (AudioEngine &eng,
        } else {
 
                if (load_state (_current_snapshot_name)) {
-                       throw failed_constructor ();
+                       throw SessionException (_("Failed to load state"));
                }
-       
+
                /* try to get sample rate from XML state so that we
                 * can influence the SR if we set up the audio
                 * engine.
@@ -326,20 +356,20 @@ Session::Session (AudioEngine &eng,
 
                if (state_tree) {
                        const XMLProperty* prop;
-                       if ((prop = state_tree->root()->property (X_("sample-rate"))) != 0) {           
+                       if ((prop = state_tree->root()->property (X_("sample-rate"))) != 0) {
                                sr = atoi (prop->value());
                        }
                }
 
                if (ensure_engine (sr)) {
                        destroy ();
-                       throw failed_constructor ();
+                       throw SessionException (_("Cannot connect to audio/midi engine"));
                }
        }
 
        if (post_engine_init ()) {
                destroy ();
-               throw failed_constructor ();
+               throw SessionException (_("Cannot configure audio/midi engine with session parameters"));
        }
 
        store_recent_sessions (_name, _path);
@@ -358,8 +388,6 @@ Session::Session (AudioEngine &eng,
        StartTimeChanged.connect_same_thread (*this, boost::bind (&Session::start_time_changed, this, _1));
        EndTimeChanged.connect_same_thread (*this, boost::bind (&Session::end_time_changed, this, _1));
 
-       _is_new = false;
-
        emit_thread_start ();
 
        /* hook us up to the engine since we are now completely constructed */
@@ -369,15 +397,60 @@ Session::Session (AudioEngine &eng,
        _engine.set_session (this);
        _engine.reset_timebase ();
 
-       BootMessage (_("Session loading complete"));
+#ifdef USE_TRACKS_CODE_FEATURES
+
+       EngineStateController::instance()->set_session(this);
+
+       if (_is_new ) {
+               if ( ARDOUR::Profile->get_trx () ) {
 
+                       /* Waves Tracks: fill session with tracks basing on the amount of inputs.
+                        * each available input must have corresponding track when session starts.
+                        */
+
+                       uint32_t how_many (0);
+
+                       std::vector<std::string> inputs;
+                       EngineStateController::instance()->get_physical_audio_inputs(inputs);
+
+                       how_many = inputs.size();
+
+                       list<boost::shared_ptr<AudioTrack> > tracks;
+
+                       // Track names after driver
+                       if (Config->get_tracks_auto_naming() == NameAfterDriver) {
+                               string track_name = "";
+                               for (std::vector<string>::size_type i = 0; i < inputs.size(); ++i) {
+                                       string track_name;
+                                       track_name = inputs[i];
+                                       replace_all (track_name, "system:capture", "");
+
+                                       list<boost::shared_ptr<AudioTrack> > single_track = new_audio_track (1, 1, Normal, 0, 1, track_name);
+                                       tracks.insert(tracks.begin(), single_track.front());
+                               }
+                       } else { // Default track names
+                               tracks = new_audio_track (1, 1, Normal, 0, how_many, string());
+                       }
+
+                       if (tracks.size() != how_many) {
+                               destroy ();
+                               throw failed_constructor ();
+                       }
+               }
+       }
+#endif
+
+       _is_new = false;
+       session_loaded ();
+
+       BootMessage (_("Session loading complete"));
 }
 
 Session::~Session ()
 {
-#ifdef PT_TIMING       
+#ifdef PT_TIMING
        ST.dump ("ST.dump");
-#endif 
+#endif
        destroy ();
 }
 
@@ -420,7 +493,7 @@ Session::immediately_post_engine ()
         * know that the engine is running, but before we either create a
         * session or set state for an existing one.
         */
-        
+
        if (how_many_dsp_threads () > 1) {
                /* For now, only create the graph if we are using >1 DSP threads, as
                   it is a bit slower than the old code with 1 thread.
@@ -477,8 +550,18 @@ Session::destroy ()
 
        drop_connections ();
 
+       /* shutdown control surface protocols while we still have ports
+          and the engine to move data to any devices.
+       */
+
+       ControlProtocolManager::instance().drop_protocols ();
+
        _engine.remove_session ();
 
+#ifdef USE_TRACKS_CODE_FEATURES
+       EngineStateController::instance()->remove_session();
+#endif
+
        /* deregister all ports - there will be no process or any other
         * callbacks from the engine any more.
         */
@@ -503,7 +586,7 @@ Session::destroy ()
        _butler->drop_references ();
        delete _butler;
        _butler = 0;
-       
+
        delete _all_route_group;
 
        DEBUG_TRACE (DEBUG::Destruction, "delete route groups\n");
@@ -592,7 +675,7 @@ Session::destroy ()
        delete _locations; _locations = 0;
 
        delete _tempo_map;
-       
+
        DEBUG_TRACE (DEBUG::Destruction, "Session::destroy() done\n");
 
 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
@@ -604,10 +687,10 @@ void
 Session::setup_ltc ()
 {
        XMLNode* child = 0;
-       
+
        _ltc_input.reset (new IO (*this, X_("LTC In"), IO::Input));
        _ltc_output.reset (new IO (*this, X_("LTC Out"), IO::Output));
-       
+
        if (state_tree && (child = find_named_node (*state_tree->root(), X_("LTC In"))) != 0) {
                _ltc_input->set_state (*(child->children().front()), Stateful::loading_state_version);
        } else {
@@ -617,7 +700,7 @@ Session::setup_ltc ()
                }
                reconnect_ltc_input ();
        }
-       
+
        if (state_tree && (child = find_named_node (*state_tree->root(), X_("LTC Out"))) != 0) {
                _ltc_output->set_state (*(child->children().front()), Stateful::loading_state_version);
        } else {
@@ -627,11 +710,11 @@ Session::setup_ltc ()
                }
                reconnect_ltc_output ();
        }
-       
+
        /* fix up names of LTC ports because we don't want the normal
         * IO style of NAME/TYPE-{in,out}N
         */
-       
+
        _ltc_input->nth (0)->set_name (X_("LTC-in"));
        _ltc_output->nth (0)->set_name (X_("LTC-out"));
 }
@@ -652,11 +735,11 @@ Session::setup_click ()
 
 void
 Session::setup_click_state (const XMLNode* node)
-{      
+{
        const XMLNode* child = 0;
-       
+
        if (node && (child = find_named_node (*node, "Click")) != 0) {
-               
+
                /* existing state for Click */
                int c = 0;
 
@@ -672,7 +755,7 @@ Session::setup_click_state (const XMLNode* node)
                                }
                        }
                }
-                       
+
                if (c == 0) {
                        _clicking = Config->get_clicking ();
 
@@ -738,10 +821,10 @@ Session::setup_bundles ()
        /* mono output bundles */
 
        for (uint32_t np = 0; np < outputs[DataType::AUDIO].size(); ++np) {
-               char buf[32];
+               char buf[64];
                std::string pn = _engine.get_pretty_name_by_name (outputs[DataType::AUDIO][np]);
                if (!pn.empty()) {
-                       snprintf (buf, sizeof (buf), _("out %s"), pn.substr(0,12).c_str());
+                       snprintf (buf, sizeof (buf), _("out %s"), pn.c_str());
                } else {
                        snprintf (buf, sizeof (buf), _("out %" PRIu32), np+1);
                }
@@ -772,10 +855,10 @@ Session::setup_bundles ()
        /* mono input bundles */
 
        for (uint32_t np = 0; np < inputs[DataType::AUDIO].size(); ++np) {
-               char buf[32];
+               char buf[64];
                std::string pn = _engine.get_pretty_name_by_name (inputs[DataType::AUDIO][np]);
                if (!pn.empty()) {
-                       snprintf (buf, sizeof (buf), _("in %s"), pn.substr(0,12).c_str());
+                       snprintf (buf, sizeof (buf), _("in %s"), pn.c_str());
                } else {
                        snprintf (buf, sizeof (buf), _("in %" PRIu32), np+1);
                }
@@ -846,24 +929,30 @@ Session::auto_connect_master_bus ()
        if (!_master_out || !Config->get_auto_connect_standard_busses() || _monitor_out) {
                return;
        }
-               
+
+       // Waves Tracks: Do not connect master bas for Tracks if AutoConnectMaster option is not set
+       // In this case it means "Multi Out" output mode
+       if (ARDOUR::Profile->get_trx() && !(Config->get_output_auto_connect() & AutoConnectMaster) ) {
+               return;
+       }
+
        /* if requested auto-connect the outputs to the first N physical ports.
         */
-       
+
        uint32_t limit = _master_out->n_outputs().n_total();
        vector<string> outputs[DataType::num_types];
-       
+
        for (uint32_t i = 0; i < DataType::num_types; ++i) {
                _engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
        }
-       
+
        for (uint32_t n = 0; n < limit; ++n) {
                boost::shared_ptr<Port> p = _master_out->output()->nth (n);
                string connect_to;
                if (outputs[p->type()].size() > n) {
                        connect_to = outputs[p->type()][n];
                }
-               
+
                if (!connect_to.empty() && p->connected_to (connect_to) == false) {
                        if (_master_out->output()->connect (p, connect_to, this)) {
                                error << string_compose (_("cannot connect master output %1 to %2"), n, connect_to)
@@ -877,7 +966,7 @@ Session::auto_connect_master_bus ()
 void
 Session::remove_monitor_section ()
 {
-       if (!_monitor_out) {
+       if (!_monitor_out || Profile->get_trx()) {
                return;
        }
 
@@ -894,20 +983,20 @@ Session::remove_monitor_section ()
                /* Hold process lock while doing this so that we don't hear bits and
                 * pieces of audio as we work on each route.
                 */
-               
+
                Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
-               
+
                /* Connect tracks to monitor section. Note that in an
                   existing session, the internal sends will already exist, but we want the
                   routes to notice that they connect to the control out specifically.
                */
-               
-               
+
+
                boost::shared_ptr<RouteList> r = routes.reader ();
                PBD::Unwinder<bool> uw (ignore_route_processor_changes, true);
-               
+
                for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
-                       
+
                        if ((*x)->is_monitor()) {
                                /* relax */
                        } else if ((*x)->is_master()) {
@@ -931,7 +1020,7 @@ Session::add_monitor_section ()
 {
        RouteList rl;
 
-       if (_monitor_out || !_master_out) {
+       if (_monitor_out || !_master_out || Profile->get_trx()) {
                return;
        }
 
@@ -944,25 +1033,28 @@ Session::add_monitor_section ()
 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
        // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
 #endif
-       {
+       try {
                Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
                r->input()->ensure_io (_master_out->output()->n_ports(), false, this);
                r->output()->ensure_io (_master_out->output()->n_ports(), false, this);
+       } catch (...) {
+               error << _("Cannot create monitor section. 'Monitor' Port name is not unique.") << endmsg;
+               return;
        }
 
        rl.push_back (r);
        add_routes (rl, false, false, false);
-       
+
        assert (_monitor_out);
 
        /* AUDIO ONLY as of june 29th 2009, because listen semantics for anything else
           are undefined, at best.
        */
-       
+
        uint32_t limit = _monitor_out->n_inputs().n_audio();
-       
+
        if (_master_out) {
-               
+
                /* connect the inputs to the master bus outputs. this
                 * represents a separate data feed from the internal sends from
                 * each route. as of jan 2011, it allows the monitor section to
@@ -976,7 +1068,7 @@ Session::add_monitor_section ()
                for (uint32_t n = 0; n < limit; ++n) {
                        boost::shared_ptr<AudioPort> p = _monitor_out->input()->ports().nth_audio_port (n);
                        boost::shared_ptr<AudioPort> o = _master_out->output()->ports().nth_audio_port (n);
-                       
+
                        if (o) {
                                string connect_to = o->name();
                                if (_monitor_out->input()->connect (p, connect_to, this)) {
@@ -987,16 +1079,16 @@ Session::add_monitor_section ()
                        }
                }
        }
-       
+
        /* if monitor section is not connected, connect it to physical outs
         */
-       
+
        if (Config->get_auto_connect_standard_busses() && !_monitor_out->output()->connected ()) {
-               
+
                if (!Config->get_monitor_bus_preferred_bundle().empty()) {
-                       
+
                        boost::shared_ptr<Bundle> b = bundle_by_name (Config->get_monitor_bus_preferred_bundle());
-                       
+
                        if (b) {
                                _monitor_out->output()->connect_ports_to_bundle (b, true, this);
                        } else {
@@ -1004,9 +1096,9 @@ Session::add_monitor_section ()
                                                           Config->get_monitor_bus_preferred_bundle())
                                        << endmsg;
                        }
-                       
+
                } else {
-                       
+
                        /* Monitor bus is audio only */
 
                        vector<string> outputs[DataType::num_types];
@@ -1017,17 +1109,17 @@ Session::add_monitor_section ()
 
                        uint32_t mod = outputs[DataType::AUDIO].size();
                        uint32_t limit = _monitor_out->n_outputs().get (DataType::AUDIO);
-                       
+
                        if (mod != 0) {
-                               
+
                                for (uint32_t n = 0; n < limit; ++n) {
-                                       
+
                                        boost::shared_ptr<Port> p = _monitor_out->output()->ports().port(DataType::AUDIO, n);
                                        string connect_to;
                                        if (outputs[DataType::AUDIO].size() > (n % mod)) {
                                                connect_to = outputs[DataType::AUDIO][n % mod];
                                        }
-                                       
+
                                        if (!connect_to.empty()) {
                                                if (_monitor_out->output()->connect (p, connect_to, this)) {
                                                        error << string_compose (
@@ -1045,7 +1137,7 @@ Session::add_monitor_section ()
        /* Hold process lock while doing this so that we don't hear bits and
         * pieces of audio as we work on each route.
         */
-        
+
        Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
 
        /* Connect tracks to monitor section. Note that in an
@@ -1059,7 +1151,7 @@ Session::add_monitor_section ()
        PBD::Unwinder<bool> uw (ignore_route_processor_changes, true);
 
        for (RouteList::iterator x = rls->begin(); x != rls->end(); ++x) {
-               
+
                if ((*x)->is_monitor()) {
                        /* relax */
                } else if ((*x)->is_master()) {
@@ -1079,7 +1171,7 @@ Session::reset_monitor_section ()
 {
        /* Process lock should be held by the caller.*/
 
-       if (!_monitor_out) {
+       if (!_monitor_out || Profile->get_trx()) {
                return;
        }
 
@@ -1378,6 +1470,19 @@ Session::auto_loop_changed (Location* location)
                clear_events (SessionEvent::AutoLoop);
        }
 
+       /* possibly move playhead if not rolling; if we are rolling we'll move
+          to the loop start on stop if that is appropriate.
+        */
+
+       framepos_t pos;
+
+       if (!transport_rolling() && select_playhead_priority_target (pos)) {
+               if (pos == location->start()) {
+                       request_locate (pos);
+               }
+       }
+
+
        last_loopend = location->end();
        set_dirty ();
 }
@@ -1427,14 +1532,14 @@ Session::set_session_extents (framepos_t start, framepos_t end)
                //if there is no existing session, we need to make a new session location  (should never happen)
                existing = new Location (*this, 0, 0, _("session"), Location::IsSessionRange);
        }
-       
+
        if (end <= start) {
                error << _("Session: you can't use that location for session start/end)") << endmsg;
                return;
        }
 
        existing->set( start, end );
-       
+
        set_dirty();
 }
 
@@ -1472,9 +1577,21 @@ Session::set_auto_loop_location (Location* location)
        location->StartChanged.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, location));
        location->EndChanged.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, location));
        location->Changed.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, location));
+       location->FlagsChanged.connect_same_thread (loop_connections, boost::bind (&Session::auto_loop_changed, this, location));
 
        location->set_auto_loop (true, this);
 
+       if (Config->get_loop_is_mode() && play_loop && Config->get_seamless_loop()) {
+               // set all tracks to use internal looping
+               boost::shared_ptr<RouteList> rl = routes.reader ();
+               for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
+                       boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
+                       if (tr && !tr->hidden()) {
+                               tr->set_loop (location);
+                       }
+               }
+       }
+
        /* take care of our stuff first */
 
        auto_loop_changed (location);
@@ -1484,12 +1601,6 @@ Session::set_auto_loop_location (Location* location)
        auto_loop_location_changed (location);
 }
 
-void
-Session::update_loop (Location*)
-{
-       set_dirty ();
-}
-
 void
 Session::update_marks (Location*)
 {
@@ -1499,10 +1610,10 @@ Session::update_marks (Location*)
 void
 Session::update_skips (Location* loc, bool consolidate)
 {
-    if (_ignore_skips_updates) {
-        return;
-    }
-    
+       if (_ignore_skips_updates) {
+               return;
+       }
+
        Locations::LocationList skips;
 
         if (consolidate) {
@@ -1511,7 +1622,7 @@ Session::update_skips (Location* loc, bool consolidate)
         }
 
        sync_locations_to_skips ();
-        
+
        set_dirty ();
 }
 
@@ -1533,7 +1644,7 @@ Session::consolidate_skips (Location* loc)
                         ++l;
                         continue;
                 }
-                        
+
                 switch (Evoral::coverage ((*l)->start(), (*l)->end(), loc->start(), loc->end())) {
                 case Evoral::OverlapInternal:
                 case Evoral::OverlapExternal:
@@ -1572,9 +1683,9 @@ Session::_sync_locations_to_skips ()
        Locations::LocationList const & locs (_locations->list());
 
        for (Locations::LocationList::const_iterator i = locs.begin(); i != locs.end(); ++i) {
-               
+
                Location* location = *i;
-               
+
                if (location->is_skip() && location->is_skipping()) {
                        SessionEvent* ev = new SessionEvent (SessionEvent::Skip, SessionEvent::Add, location->start(), location->end(), 1.0);
                        queue_event (ev);
@@ -1593,7 +1704,7 @@ Session::location_added (Location *location)
         if (location->is_auto_loop()) {
                 set_auto_loop_location (location);
         }
-        
+
         if (location->is_session_range()) {
                 /* no need for any signal handling or event setting with the session range,
                    because we keep a direct reference to it and use its start/end directly.
@@ -1601,6 +1712,15 @@ Session::location_added (Location *location)
                 _session_range_location = location;
         }
 
+        if (location->is_mark()) {
+                /* listen for per-location signals that require us to do any * global updates for marks */
+
+                location->StartChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location));
+                location->EndChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location));
+                location->Changed.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location));
+                location->FlagsChanged.connect_same_thread (skip_update_connections, boost::bind (&Session::update_marks, this, location));
+        }
+
         if (location->is_skip()) {
                 /* listen for per-location signals that require us to update skip-locate events */
 
@@ -1622,7 +1742,7 @@ Session::location_removed (Location *location)
                set_auto_loop_location (0);
                set_track_loop (false);
         }
-        
+
         if (location->is_auto_punch()) {
                 set_auto_punch_location (0);
         }
@@ -1633,7 +1753,7 @@ Session::location_removed (Location *location)
         }
 
         if (location->is_skip()) {
-                
+
                 update_skips (location, false);
         }
 
@@ -1649,15 +1769,20 @@ Session::locations_changed ()
 void
 Session::_locations_changed (const Locations::LocationList& locations)
 {
-        /* There was some mass-change in the Locations object. 
+        /* There was some mass-change in the Locations object.
 
            We might be re-adding a location here but it doesn't actually matter
            for all the locations that the Session takes an interest in.
         */
 
-       for (Locations::LocationList::const_iterator i = locations.begin(); i != locations.end(); ++i) {
-                location_added (*i);
-        }
+       {
+               PBD::Unwinder<bool> protect_ignore_skip_updates (_ignore_skips_updates, true);
+               for (Locations::LocationList::const_iterator i = locations.begin(); i != locations.end(); ++i) {
+                       location_added (*i);
+               }
+       }
+
+       update_skips (NULL, false);
 }
 
 void
@@ -1674,7 +1799,7 @@ Session::enable_record ()
                if (rs == Recording) {
                        break;
                }
-               
+
                if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
 
                        _last_record_location = _transport_frame;
@@ -1697,7 +1822,7 @@ Session::disable_record (bool rt_context, bool force)
 
        if ((rs = (RecordState) g_atomic_int_get (&_record_status)) != Disabled) {
 
-               if ((!Config->get_latched_record_enable () && !play_loop) || force) {
+               if (!Config->get_latched_record_enable () || force) {
                        g_atomic_int_set (&_record_status, Disabled);
                        send_immediate_mmc (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
                } else {
@@ -1835,6 +1960,7 @@ Session::set_frame_rate (framecnt_t frames_per_second)
        sync_time_vars();
 
        clear_clicks ();
+       reset_write_sources (false);
 
        // XXX we need some equivalent to this, somehow
        // SndFileSource::setup_standard_crossfades (frames_per_second);
@@ -1852,7 +1978,7 @@ Session::set_block_size (pframes_t nframes)
           ::process(). It is therefore fine to do things that block
           here.
        */
-       
+
        {
                current_block_size = nframes;
 
@@ -1975,7 +2101,7 @@ Session::resort_routes_using (boost::shared_ptr<RouteList> r)
        /* We are going to build a directed graph of our routes;
           this is where the edges of that graph are put.
        */
-       
+
        GraphEdges edges;
 
        /* Go through all routes doing two things:
@@ -1988,7 +2114,7 @@ Session::resort_routes_using (boost::shared_ptr<RouteList> r)
         *    routes directly or indirectly feed them.  This information
         *    is used by the solo code.
         */
-          
+
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
 
                /* Clear out the route's list of direct or indirect feeds */
@@ -2012,7 +2138,7 @@ Session::resort_routes_using (boost::shared_ptr<RouteList> r)
 
        /* Attempt a topological sort of the route graph */
        boost::shared_ptr<RouteList> sorted_routes = topological_sort (r, edges);
-       
+
        if (sorted_routes) {
                /* We got a satisfactory topological sort, so there is no feedback;
                   use this new graph.
@@ -2023,7 +2149,7 @@ Session::resort_routes_using (boost::shared_ptr<RouteList> r)
                if (_process_graph) {
                        _process_graph->rechain (sorted_routes, edges);
                }
-               
+
                _current_route_graph = edges;
 
                /* Complete the building of the routes' lists of what directly
@@ -2054,7 +2180,7 @@ Session::resort_routes_using (boost::shared_ptr<RouteList> r)
                   so the solo code will think that everything is still connected
                   as it was before.
                */
-               
+
                FeedbackDetected (); /* EMIT SIGNAL */
        }
 
@@ -2073,23 +2199,38 @@ Session::resort_routes_using (boost::shared_ptr<RouteList> r)
  *  and \a id do not reflect a free route name.
  */
 bool
-Session::find_route_name (string const & base, uint32_t& id, char* name, size_t name_len, bool definitely_add_number)
+Session::find_route_name (string const & base, uint32_t& id, string& name, bool definitely_add_number)
 {
+       /* the base may conflict with ports that do not belong to existing
+          routes, but hidden objects like the click track. So check port names
+          before anything else.
+       */
+
+       for (vector<string>::const_iterator reserved = reserved_io_names.begin(); reserved != reserved_io_names.end(); ++reserved) {
+               if (base == *reserved) {
+                       definitely_add_number = true;
+                       if (id < 1) {
+                               id = 1;
+                       }
+                       break;
+               }
+       }
+
        if (!definitely_add_number && route_by_name (base) == 0) {
                /* juse use the base */
-               snprintf (name, name_len, "%s", base.c_str());
+               name = base;
                return true;
        }
 
        do {
-               snprintf (name, name_len, "%s %" PRIu32, base.c_str(), id);
+               name = string_compose ("%1 %2", base, id);
 
                if (route_by_name (name) == 0) {
                        return true;
                }
 
                ++id;
-               
+
        } while (id < (UINT_MAX-1));
 
        return false;
@@ -2113,24 +2254,44 @@ Session::count_existing_track_channels (ChanCount& in, ChanCount& out)
        }
 }
 
+string
+Session::default_track_name_pattern (DataType t)
+{
+       switch (t) {
+       case DataType::AUDIO:
+               if (Profile->get_trx()) {
+                       return _("Track ");
+               } else {
+                       return _("Audio ");
+               }
+               break;
+
+       case DataType::MIDI:
+               return _("MIDI ");
+       }
+
+       return "";
+}
+
 /** Caller must not hold process lock
  *  @param name_template string to use for the start of the name, or "" to use "MIDI".
  *  @param instrument plugin info for the instrument to insert pre-fader, if any
  */
 list<boost::shared_ptr<MidiTrack> >
-Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost::shared_ptr<PluginInfo> instrument, 
+Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost::shared_ptr<PluginInfo> instrument,
                         TrackMode mode, RouteGroup* route_group, uint32_t how_many, string name_template)
 {
-       char track_name[32];
+       string track_name;
        uint32_t track_id = 0;
        string port;
        RouteList new_routes;
        list<boost::shared_ptr<MidiTrack> > ret;
 
-       bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("MIDI");
+       const string name_pattern = default_track_name_pattern (DataType::MIDI);
+       bool const use_number = (how_many != 1) || name_template.empty () || (name_template == name_pattern);
 
        while (how_many) {
-               if (!find_route_name (name_template.empty() ? _("MIDI") : name_template, ++track_id, track_name, sizeof(track_name), use_number)) {
+               if (!find_route_name (name_template.empty() ? _("MIDI") : name_template, ++track_id, track_name, use_number)) {
                        error << "cannot find name for new midi track" << endmsg;
                        goto failed;
                }
@@ -2152,7 +2313,7 @@ Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost:
                        {
                                Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
                                if (track->input()->ensure_io (input, false, this)) {
-                                       error << "cannot configure " << input << " out configuration for new midi track" << endmsg;     
+                                       error << "cannot configure " << input << " out configuration for new midi track" << endmsg;
                                        goto failed;
                                }
 
@@ -2176,6 +2337,8 @@ Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost:
 
                        new_routes.push_back (track);
                        ret.push_back (track);
+
+                       RouteAddedOrRemoved (true); /* EMIT SIGNAL */
                }
 
                catch (failed_constructor &err) {
@@ -2195,14 +2358,18 @@ Session::new_midi_track (const ChanCount& input, const ChanCount& output, boost:
   failed:
        if (!new_routes.empty()) {
                StateProtector sp (this);
-               add_routes (new_routes, true, true, true);
+               if (Profile->get_trx()) {
+                       add_routes (new_routes, false, false, false);
+               } else {
+                       add_routes (new_routes, true, true, false);
+               }
 
                if (instrument) {
                        for (RouteList::iterator r = new_routes.begin(); r != new_routes.end(); ++r) {
                                PluginPtr plugin = instrument->load (*this);
                                boost::shared_ptr<Processor> p (new PluginInsert (*this, plugin));
                                (*r)->add_processor (p, PreFader);
-                               
+
                        }
                }
        }
@@ -2325,6 +2492,17 @@ Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing
                        for (uint32_t i = output_start.get(*t); i < route->n_outputs().get(*t); ++i) {
                                string port;
 
+                               /* Waves Tracks:
+                                * do not create new connections if we reached the limit of physical outputs
+                                * in Multi Out mode
+                                */
+
+                               if (!(Config->get_output_auto_connect() & AutoConnectMaster) &&
+                                   ARDOUR::Profile->get_trx () &&
+                                   existing_outputs.get(*t) == nphysical_out ) {
+                                       break;
+                               }
+
                                if ((*t) == DataType::MIDI && (Config->get_output_auto_connect() & AutoConnectPhysical)) {
                                        port = physoutputs[(out_offset.get(*t) + i) % nphysical_out];
                                } else if ((*t) == DataType::AUDIO && (Config->get_output_auto_connect() & AutoConnectMaster)) {
@@ -2350,31 +2528,309 @@ Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing
        }
 }
 
+#ifdef USE_TRACKS_CODE_FEATURES
+
+static bool
+compare_routes_by_remote_id (const boost::shared_ptr<Route>& route1, const boost::shared_ptr<Route>& route2)
+{
+       return route1->remote_control_id() < route2->remote_control_id();
+}
+
 void
 Session::reconnect_existing_routes (bool withLock, bool reconnect_master, bool reconnect_inputs, bool reconnect_outputs)
 {
-        /* TRX does stuff here, ardour does not (but probably should). This is called after an engine reset (in particular).
-         */
+       // it is not allowed to perform connection
+       if (!IO::connecting_legal) {
+               return;
+       }
+
+       // if we are deleting routes we will call this once at the end
+       if (_route_deletion_in_progress) {
+               return;
+       }
+
+       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock (), Glib::Threads::NOT_LOCK);
+
+       if (withLock) {
+               lm.acquire ();
+       }
+
+       // We need to disconnect the route's inputs and outputs first
+       // basing on autoconnect configuration
+       bool reconnectIputs = !(Config->get_input_auto_connect() & ManualConnect) && reconnect_inputs;
+       bool reconnectOutputs = !(Config->get_output_auto_connect() & ManualConnect) && reconnect_outputs;
+
+       ChanCount existing_inputs;
+       ChanCount existing_outputs;
+       count_existing_track_channels (existing_inputs, existing_outputs);
+
+       //ChanCount inputs = ChanCount::ZERO;
+       //ChanCount outputs = ChanCount::ZERO;
+
+       RouteList existing_routes = *routes.reader ();
+       existing_routes.sort (compare_routes_by_remote_id);
+
+       {
+               PBD::Unwinder<bool> protect_ignore_changes (_reconnecting_routes_in_progress, true);
+
+               vector<string> physinputs;
+               vector<string> physoutputs;
+
+               EngineStateController::instance()->get_physical_audio_outputs(physoutputs);
+               EngineStateController::instance()->get_physical_audio_inputs(physinputs);
+
+               uint32_t input_n = 0;
+               uint32_t output_n = 0;
+               RouteList::iterator rIter = existing_routes.begin();
+               const AutoConnectOption current_input_auto_connection (Config->get_input_auto_connect());
+               const AutoConnectOption current_output_auto_connection (Config->get_output_auto_connect());
+               for (; rIter != existing_routes.end(); ++rIter) {
+                       if (*rIter == _master_out || *rIter == _monitor_out ) {
+                               continue;
+                       }
+
+                       if (current_output_auto_connection == AutoConnectPhysical) {
+                               (*rIter)->amp()->deactivate();
+                       } else if (current_output_auto_connection == AutoConnectMaster) {
+                               (*rIter)->amp()->activate();
+                       }
+
+                       if (reconnectIputs) {
+                               (*rIter)->input()->disconnect (this); //GZ: check this; could be heavy
+
+                               for (uint32_t route_input_n = 0; route_input_n < (*rIter)->n_inputs().get(DataType::AUDIO); ++route_input_n) {
+
+                                       if (current_input_auto_connection & AutoConnectPhysical) {
+
+                                               if ( input_n == physinputs.size() ) {
+                                                       break;
+                                               }
+
+                                               string port = physinputs[input_n];
+
+                                               if (port.empty() ) {
+                                                       error << "Physical Input number "<< input_n << " is unavailable and cannot be connected" << endmsg;
+                                               }
+
+                                               //GZ: check this; could be heavy
+                                               (*rIter)->input()->connect ((*rIter)->input()->ports().port(DataType::AUDIO, route_input_n), port, this);
+                                               ++input_n;
+                                       }
+                               }
+                       }
+
+                       if (reconnectOutputs) {
+
+                               //normalize route ouptuts: reduce the amount outputs to be equal to the amount of inputs
+                               if (current_output_auto_connection & AutoConnectPhysical) {
+
+                                       //GZ: check this; could be heavy
+                                       (*rIter)->output()->disconnect (this);
+                                       size_t route_inputs_count = (*rIter)->n_inputs().get(DataType::AUDIO);
+
+                                       //GZ: check this; could be heavy
+                                       (*rIter)->output()->ensure_io(ChanCount(DataType::AUDIO, route_inputs_count), false, this );
+
+                               } else if (current_output_auto_connection & AutoConnectMaster){
+
+                                       if (!reconnect_master) {
+                                               continue;
+                                       }
+
+                                       //GZ: check this; could be heavy
+                                       (*rIter)->output()->disconnect (this);
+
+                                       if (_master_out) {
+                                               uint32_t master_inputs_count = _master_out->n_inputs().get(DataType::AUDIO);
+                                               (*rIter)->output()->ensure_io(ChanCount(DataType::AUDIO, master_inputs_count), false, this );
+                                       } else {
+                                               error << error << "Master bus is not available" << endmsg;
+                                               break;
+                                       }
+                               }
+
+                               for (uint32_t route_output_n = 0; route_output_n < (*rIter)->n_outputs().get(DataType::AUDIO); ++route_output_n) {
+                                       if (current_output_auto_connection & AutoConnectPhysical) {
+
+                                               if ( output_n == physoutputs.size() ) {
+                                                       break;
+                                               }
+
+                                               string port = physoutputs[output_n];
+
+                                               if (port.empty() ) {
+                                                       error << "Physical Output number "<< output_n << " is unavailable and cannot be connected" << endmsg;
+                                               }
+
+                                               //GZ: check this; could be heavy
+                                               (*rIter)->output()->connect ((*rIter)->output()->ports().port(DataType::AUDIO, route_output_n), port, this);
+                                               ++output_n;
+
+                                       } else if (current_output_auto_connection & AutoConnectMaster) {
+
+                                               if ( route_output_n == _master_out->n_inputs().get(DataType::AUDIO) ) {
+                                                       break;
+                                               }
+
+                                               // connect to master bus
+                                               string port = _master_out->input()->ports().port(DataType::AUDIO, route_output_n)->name();
+
+                                               if (port.empty() ) {
+                                                       error << "MasterBus Input number "<< route_output_n << " is unavailable and cannot be connected" << endmsg;
+                                               }
+
+
+                                               //GZ: check this; could be heavy
+                                               (*rIter)->output()->connect ((*rIter)->output()->ports().port(DataType::AUDIO, route_output_n), port, this);
+
+                                       }
+                               }
+                       }
+
+                       //auto_connect_route (*rIter, inputs, outputs, false, reconnectIputs);
+               }
+
+               _master_out->output()->disconnect (this);
+               auto_connect_master_bus ();
+       }
+
+       graph_reordered ();
+
+       session_routes_reconnected (); /* EMIT SIGNAL */
 }
 
+void
+Session::reconnect_midi_scene_ports(bool inputs)
+{
+    if (inputs ) {
+
+        boost::shared_ptr<MidiPort> scene_in_ptr = scene_in();
+        if (scene_in_ptr) {
+            scene_in_ptr->disconnect_all ();
+
+            std::vector<EngineStateController::MidiPortState> midi_port_states;
+            EngineStateController::instance()->get_physical_midi_input_states (midi_port_states);
+
+            std::vector<EngineStateController::MidiPortState>::iterator state_iter = midi_port_states.begin();
+
+            for (; state_iter != midi_port_states.end(); ++state_iter) {
+                if (state_iter->active && state_iter->available && state_iter->scene_connected) {
+                    scene_in_ptr->connect (state_iter->name);
+                }
+            }
+        }
+
+    } else {
+
+        boost::shared_ptr<MidiPort> scene_out_ptr = scene_out();
+
+        if (scene_out_ptr ) {
+            scene_out_ptr->disconnect_all ();
+
+            std::vector<EngineStateController::MidiPortState> midi_port_states;
+            EngineStateController::instance()->get_physical_midi_output_states (midi_port_states);
+
+            std::vector<EngineStateController::MidiPortState>::iterator state_iter = midi_port_states.begin();
+
+            for (; state_iter != midi_port_states.end(); ++state_iter) {
+                if (state_iter->active && state_iter->available && state_iter->scene_connected) {
+                    scene_out_ptr->connect (state_iter->name);
+                }
+            }
+        }
+    }
+}
+
+void
+Session::reconnect_mtc_ports ()
+{
+       boost::shared_ptr<MidiPort> mtc_in_ptr = _midi_ports->mtc_input_port();
+
+       if (!mtc_in_ptr) {
+               return;
+       }
+
+       mtc_in_ptr->disconnect_all ();
+
+       std::vector<EngineStateController::MidiPortState> midi_port_states;
+       EngineStateController::instance()->get_physical_midi_input_states (midi_port_states);
+
+       std::vector<EngineStateController::MidiPortState>::iterator state_iter = midi_port_states.begin();
+
+       for (; state_iter != midi_port_states.end(); ++state_iter) {
+               if (state_iter->available && state_iter->mtc_in) {
+                       mtc_in_ptr->connect (state_iter->name);
+               }
+       }
+
+       if (!_midi_ports->mtc_input_port ()->connected () &&
+           config.get_external_sync () &&
+           (Config->get_sync_source () == MTC) ) {
+               config.set_external_sync (false);
+       }
+
+       if ( ARDOUR::Profile->get_trx () ) {
+               // Tracks need this signal to update timecode_source_dropdown
+               MtcOrLtcInputPortChanged (); //emit signal
+       }
+}
+
+void
+Session::reconnect_mmc_ports(bool inputs)
+{
+       if (inputs ) { // get all enabled midi input ports
+
+               boost::shared_ptr<MidiPort> mmc_in_ptr = _midi_ports->mmc_in();
+               if (mmc_in_ptr) {
+                       mmc_in_ptr->disconnect_all ();
+                       std::vector<std::string> enabled_midi_inputs;
+                       EngineStateController::instance()->get_physical_midi_inputs (enabled_midi_inputs);
+
+                       std::vector<std::string>::iterator port_iter = enabled_midi_inputs.begin();
+
+                       for (; port_iter != enabled_midi_inputs.end(); ++port_iter) {
+                               mmc_in_ptr->connect (*port_iter);
+                       }
+
+               }
+       } else { // get all enabled midi output ports
+
+               boost::shared_ptr<MidiPort> mmc_out_ptr = _midi_ports->mmc_out();
+               if (mmc_out_ptr ) {
+                       mmc_out_ptr->disconnect_all ();
+                       std::vector<std::string> enabled_midi_outputs;
+                       EngineStateController::instance()->get_physical_midi_outputs (enabled_midi_outputs);
+
+                       std::vector<std::string>::iterator port_iter = enabled_midi_outputs.begin();
+
+                       for (; port_iter != enabled_midi_outputs.end(); ++port_iter) {
+                               mmc_out_ptr->connect (*port_iter);
+                       }
+               }
+       }
+}
+
+#endif
 
 /** Caller must not hold process lock
  *  @param name_template string to use for the start of the name, or "" to use "Audio".
  */
 list< boost::shared_ptr<AudioTrack> >
-Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, RouteGroup* route_group, 
+Session::new_audio_track (int input_channels, int output_channels, TrackMode mode, RouteGroup* route_group,
                          uint32_t how_many, string name_template)
 {
-       char track_name[32];
+       string track_name;
        uint32_t track_id = 0;
        string port;
        RouteList new_routes;
        list<boost::shared_ptr<AudioTrack> > ret;
 
-       bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("Audio");
+       const string name_pattern = default_track_name_pattern (DataType::AUDIO);
+       bool const use_number = (how_many != 1) || name_template.empty () || (name_template == name_pattern);
 
        while (how_many) {
-               if (!find_route_name (name_template.empty() ? _("Audio") : name_template, ++track_id, track_name, sizeof(track_name), use_number)) {
+
+               if (!find_route_name (name_template.empty() ? _(name_pattern.c_str()) : name_template, ++track_id, track_name, use_number)) {
                        error << "cannot find name for new audio track" << endmsg;
                        goto failed;
                }
@@ -2388,6 +2844,20 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
                                goto failed;
                        }
 
+                       if (ARDOUR::Profile->get_trx ()) {
+                               // TRACKS considers it's not a USE CASE, it's
+                               // a piece of behavior of the session model:
+                               //
+                               // Gain for a newly created route depends on
+                               // the current output_auto_connect mode:
+                               //
+                               //  0 for Stereo Out mode
+                               //  0 Multi Out mode
+                               if (Config->get_output_auto_connect() & AutoConnectMaster) {
+                                       track->set_gain (dB_to_coefficient (0), 0);
+                               }
+                       }
+
                        track->use_new_diskstream();
 
 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
@@ -2426,6 +2896,8 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
 
                        new_routes.push_back (track);
                        ret.push_back (track);
+
+                       RouteAddedOrRemoved (true); /* EMIT SIGNAL */
                }
 
                catch (failed_constructor &err) {
@@ -2445,7 +2917,11 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
   failed:
        if (!new_routes.empty()) {
                StateProtector sp (this);
-               add_routes (new_routes, true, true, true);
+               if (Profile->get_trx()) {
+                       add_routes (new_routes, false, false, false);
+               } else {
+                       add_routes (new_routes, true, true, false);
+               }
        }
 
        return ret;
@@ -2457,15 +2933,15 @@ Session::new_audio_track (int input_channels, int output_channels, TrackMode mod
 RouteList
 Session::new_audio_route (int input_channels, int output_channels, RouteGroup* route_group, uint32_t how_many, string name_template)
 {
-       char bus_name[32];
+       string bus_name;
        uint32_t bus_id = 0;
        string port;
        RouteList ret;
 
        bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("Bus");
-       
+
        while (how_many) {
-               if (!find_route_name (name_template.empty () ? _("Bus") : name_template, ++bus_id, bus_name, sizeof(bus_name), use_number)) {
+               if (!find_route_name (name_template.empty () ? _("Bus") : name_template, ++bus_id, bus_name, use_number)) {
                        error << "cannot find name for new audio bus" << endmsg;
                        goto failure;
                }
@@ -2509,7 +2985,9 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
                        bus->add_internal_return ();
 
                        ret.push_back (bus);
-                       
+
+                       RouteAddedOrRemoved (true); /* EMIT SIGNAL */
+
                        ARDOUR::GUIIdle ();
                }
 
@@ -2531,7 +3009,11 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
   failure:
        if (!ret.empty()) {
                StateProtector sp (this);
-               add_routes (ret, false, true, true); // autoconnect outputs only
+               if (Profile->get_trx()) {
+                       add_routes (ret, false, false, false);
+               } else {
+                       add_routes (ret, false, true, true); // autoconnect // outputs only
+               }
        }
 
        return ret;
@@ -2565,7 +3047,7 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
                node_copy.remove_property_recursively (X_("id"));
 
                try {
-                       char name[32];
+                       string name;
 
                        if (!name_base.empty()) {
 
@@ -2574,7 +3056,7 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
                                 * numbered, via the final parameter.
                                 */
 
-                               if (!find_route_name (name_base.c_str(), ++number, name, sizeof(name), (being_added > 1))) {
+                               if (!find_route_name (name_base.c_str(), ++number, name, (being_added > 1))) {
                                        fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
                                        /*NOTREACHDE*/
                                }
@@ -2582,9 +3064,9 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
                        } else {
 
                                string const route_name  = node_copy.property(X_("name"))->value ();
-                       
+
                                /* generate a new name by adding a number to the end of the template name */
-                               if (!find_route_name (route_name.c_str(), ++number, name, sizeof(name), true)) {
+                               if (!find_route_name (route_name.c_str(), ++number, name, true)) {
                                        fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
                                        abort(); /*NOTREACHED*/
                                }
@@ -2603,7 +3085,7 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
                                        }
                                }
                        }
-                       
+
                        boost::shared_ptr<Route> route (XMLRouteFactory (node_copy, 3000));
 
                        if (route == 0) {
@@ -2630,6 +3112,8 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
                        ++control_id;
 
                        ret.push_back (route);
+
+                       RouteAddedOrRemoved (true); /* EMIT SIGNAL */
                }
 
                catch (failed_constructor &err) {
@@ -2648,7 +3132,11 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
   out:
        if (!ret.empty()) {
                StateProtector sp (this);
-               add_routes (ret, true, true, true);
+               if (Profile->get_trx()) {
+                       add_routes (ret, false, false, false);
+               } else {
+                       add_routes (ret, true, true, false);
+               }
                IO::enable_connecting ();
        }
 
@@ -2670,15 +3158,17 @@ Session::add_routes (RouteList& new_routes, bool input_auto_connect, bool output
 
        update_latency (true);
        update_latency (false);
-               
+
        set_dirty();
-       
+
        if (save) {
                save_state (_current_snapshot_name);
        }
-       
+
        reassign_track_numbers();
 
+       update_route_record_state ();
+
        RouteAdded (new_routes); /* EMIT SIGNAL */
 }
 
@@ -2736,7 +3226,7 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
                if (tr) {
                        tr->PlaylistChanged.connect_same_thread (*this, boost::bind (&Session::track_playlist_changed, this, boost::weak_ptr<Track> (tr)));
                        track_playlist_changed (boost::weak_ptr<Track> (tr));
-                       tr->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Session::update_have_rec_enabled_track, this));
+                       tr->RecordEnableChanged.connect_same_thread (*this, boost::bind (&Session::update_route_record_state, this));
 
                        boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (tr);
                        if (mt) {
@@ -2770,8 +3260,8 @@ Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool
        }
 
        if (_monitor_out && IO::connecting_legal) {
-               Glib::Threads::Mutex::Lock lm (_engine.process_lock());         
-               
+               Glib::Threads::Mutex::Lock lm (_engine.process_lock());
+
                for (RouteList::iterator x = new_routes.begin(); x != new_routes.end(); ++x) {
                        if ((*x)->is_monitor()) {
                                /* relax */
@@ -2870,91 +3360,109 @@ Session::add_internal_send (boost::shared_ptr<Route> dest, boost::shared_ptr<Pro
        graph_reordered ();
 }
 
+
 void
-Session::remove_route (boost::shared_ptr<Route> route)
+Session::remove_routes (boost::shared_ptr<RouteList> routes_to_remove)
 {
-       if (route == _master_out) {
-               return;
-       }
-
-       route->set_solo (false, this);
+       PBD::Unwinder<bool> uw_flag (_route_deletion_in_progress, true);
 
-       {
+       { // RCU Writer scope
                RCUWriter<RouteList> writer (routes);
                boost::shared_ptr<RouteList> rs = writer.get_copy ();
 
-               rs->remove (route);
 
-               /* deleting the master out seems like a dumb
-                  idea, but its more of a UI policy issue
-                  than our concern.
-               */
+               for (RouteList::iterator iter = routes_to_remove->begin(); iter != routes_to_remove->end(); ++iter) {
 
-               if (route == _master_out) {
-                       _master_out = boost::shared_ptr<Route> ();
-               }
+                       if (*iter == _master_out) {
+                               continue;
+                       }
 
-               if (route == _monitor_out) {
-                       _monitor_out.reset ();
-               }
+                       (*iter)->set_solo (false, this);
 
-               /* writer goes out of scope, forces route list update */
-       }
+                       rs->remove (*iter);
 
-       update_route_solo_state ();
+                       /* deleting the master out seems like a dumb
+                          idea, but its more of a UI policy issue
+                          than our concern.
+                       */
+
+                       if (*iter == _master_out) {
+                               _master_out = boost::shared_ptr<Route> ();
+                       }
 
-       // We need to disconnect the route's inputs and outputs
+                       if (*iter == _monitor_out) {
+                               _monitor_out.reset ();
+                       }
 
-       route->input()->disconnect (0);
-       route->output()->disconnect (0);
+                       // We need to disconnect the route's inputs and outputs
 
-       /* if the route had internal sends sending to it, remove them */
-       if (route->internal_return()) {
+                       (*iter)->input()->disconnect (0);
+                       (*iter)->output()->disconnect (0);
 
-               boost::shared_ptr<RouteList> r = routes.reader ();
-               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                       boost::shared_ptr<Send> s = (*i)->internal_send_for (route);
-                       if (s) {
-                               (*i)->remove_processor (s);
+                       /* if the route had internal sends sending to it, remove them */
+                       if ((*iter)->internal_return()) {
+
+                               boost::shared_ptr<RouteList> r = routes.reader ();
+                               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+                                       boost::shared_ptr<Send> s = (*i)->internal_send_for (*iter);
+                                       if (s) {
+                                               (*i)->remove_processor (s);
+                                       }
+                               }
                        }
-               }
-       }
 
-       /* if the monitoring section had a pointer to this route, remove it */
-       if (_monitor_out && !route->is_master() && !route->is_monitor()) {
-               Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
-               PBD::Unwinder<bool> uw (ignore_route_processor_changes, true);
-               route->remove_aux_or_listen (_monitor_out);
-       }
+                       /* if the monitoring section had a pointer to this route, remove it */
+                       if (_monitor_out && !(*iter)->is_master() && !(*iter)->is_monitor()) {
+                               Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                               PBD::Unwinder<bool> uw (ignore_route_processor_changes, true);
+                               (*iter)->remove_aux_or_listen (_monitor_out);
+                       }
 
-       boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (route);
-       if (mt && mt->step_editing()) {
-               if (_step_editors > 0) {
-                       _step_editors--;
+                       boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (*iter);
+                       if (mt && mt->step_editing()) {
+                               if (_step_editors > 0) {
+                                       _step_editors--;
+                               }
+                       }
                }
-       }
 
+               /* writer goes out of scope, forces route list update */
+
+       } // end of RCU Writer scope
+
+       update_route_solo_state ();
+       RouteAddedOrRemoved (false); /* EMIT SIGNAL */
        update_latency_compensation ();
        set_dirty();
 
        /* Re-sort routes to remove the graph's current references to the one that is
         * going away, then flush old references out of the graph.
+        * Wave Tracks: reconnect routes
         */
 
-       resort_routes ();
+#ifdef USE_TRACKS_CODE_FEATURES
+               reconnect_existing_routes(true, false);
+#else
+               routes.flush (); // maybe unsafe, see below.
+               resort_routes ();
+#endif
+
        if (_process_graph) {
                _process_graph->clear_other_chain ();
        }
 
        /* get rid of it from the dead wood collection in the route list manager */
-
        /* XXX i think this is unsafe as it currently stands, but i am not sure. (pd, october 2nd, 2006) */
 
        routes.flush ();
 
-       /* try to cause everyone to drop their references */
+       /* try to cause everyone to drop their references
+        * and unregister ports from the backend
+        */
 
-       route->drop_references ();
+       for (RouteList::iterator iter = routes_to_remove->begin(); iter != routes_to_remove->end(); ++iter) {
+               (*iter)->drop_references ();
+       }
 
        Route::RemoteControlIDChange(); /* EMIT SIGNAL */
 
@@ -2963,7 +3471,17 @@ Session::remove_route (boost::shared_ptr<Route> route)
        if (save_state (_current_snapshot_name)) {
                save_history (_current_snapshot_name);
        }
+
        reassign_track_numbers();
+       update_route_record_state ();
+}
+
+void
+Session::remove_route (boost::shared_ptr<Route> route)
+{
+       boost::shared_ptr<RouteList> rl (new RouteList);
+       rl->push_back (route);
+       remove_routes (rl);
 }
 
 void
@@ -2984,10 +3502,12 @@ Session::route_listen_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
        if (route->listening_via_monitor ()) {
 
                if (Config->get_exclusive_solo()) {
-                       /* new listen: disable all other listen */
+                       /* new listen: disable all other listen, except solo-grouped channels */
+                       RouteGroup* rg = route->route_group ();
+                       bool leave_group_alone = (rg && rg->is_active() && rg->is_solo());
                        boost::shared_ptr<RouteList> r = routes.reader ();
                        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
+                               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner() || (leave_group_alone && ((*i)->route_group() == rg))) {
                                        continue;
                                }
                                (*i)->set_listen (false, this);
@@ -3010,7 +3530,7 @@ Session::route_solo_isolated_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
 
        if (!route) {
                /* should not happen */
-               error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
+               error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_isolated_changed")) << endmsg;
                return;
        }
 
@@ -3043,12 +3563,6 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                return;
        }
 
-       if (solo_update_disabled) {
-               // We know already
-               DEBUG_TRACE (DEBUG::Solo, "solo update disabled - changed ignored\n");
-               return;
-       }
-
        boost::shared_ptr<Route> route = wpr.lock ();
        assert (route);
 
@@ -3065,7 +3579,7 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
        bool leave_group_alone = (rg && rg->is_active() && rg->is_solo());
 
        if (delta == 1 && Config->get_exclusive_solo()) {
-               
+
                /* new solo: disable all other solos, but not the group if its solo-enabled */
 
                for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
@@ -3079,8 +3593,6 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
 
        DEBUG_TRACE (DEBUG::Solo, string_compose ("propagate solo change, delta = %1\n", delta));
 
-       solo_update_disabled = true;
-
        RouteList uninvolved;
 
        DEBUG_TRACE (DEBUG::Solo, string_compose ("%1\n", route->name()));
@@ -3097,7 +3609,7 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                in_signal_flow = false;
 
                DEBUG_TRACE (DEBUG::Solo, string_compose ("check feed from %1\n", (*i)->name()));
-               
+
                if ((*i)->feeds (route, &via_sends_only)) {
                        DEBUG_TRACE (DEBUG::Solo, string_compose ("\tthere is a feed from %1\n", (*i)->name()));
                        if (!via_sends_only) {
@@ -3111,7 +3623,7 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                } else {
                        DEBUG_TRACE (DEBUG::Solo, string_compose ("\tno feed from %1\n", (*i)->name()));
                }
-               
+
                DEBUG_TRACE (DEBUG::Solo, string_compose ("check feed to %1\n", (*i)->name()));
 
                if (route->feeds (*i, &via_sends_only)) {
@@ -3146,7 +3658,6 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                }
        }
 
-       solo_update_disabled = false;
        DEBUG_TRACE (DEBUG::Solo, "propagation complete\n");
 
        update_route_solo_state (r);
@@ -3231,6 +3742,12 @@ Session::io_name_is_legal (const std::string& name)
 {
        boost::shared_ptr<RouteList> r = routes.reader ();
 
+       for (vector<string>::const_iterator reserved = reserved_io_names.begin(); reserved != reserved_io_names.end(); ++reserved) {
+               if (name == *reserved) {
+                       return false;
+               }
+       }
+
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                if ((*i)->name() == name) {
                        return false;
@@ -3265,19 +3782,19 @@ Session::set_exclusive_input_active (boost::shared_ptr<RouteList> rl, bool onoff
        for (RouteList::iterator rt = rl->begin(); rt != rl->end(); ++rt) {
 
                PortSet& ps ((*rt)->input()->ports());
-               
+
                for (PortSet::iterator p = ps.begin(); p != ps.end(); ++p) {
                        p->get_connections (connections);
                }
-               
+
                for (vector<string>::iterator s = connections.begin(); s != connections.end(); ++s) {
                        routes_using_input_from (*s, rl2);
                }
-               
+
                /* scan all relevant routes to see if others are on or off */
-               
+
                bool others_are_already_on = false;
-               
+
                for (RouteList::iterator r = rl2.begin(); r != rl2.end(); ++r) {
 
                        boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (*r);
@@ -3295,11 +3812,11 @@ Session::set_exclusive_input_active (boost::shared_ptr<RouteList> rl, bool onoff
                                mt->set_input_active (onoff);
                        }
                }
-               
+
                if (flip_others) {
 
                        /* globally reverse other routes */
-                       
+
                        for (RouteList::iterator r = rl2.begin(); r != rl2.end(); ++r) {
                                if ((*r) != (*rt)) {
                                        boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (*r);
@@ -3468,9 +3985,11 @@ Session::maybe_update_session_range (framepos_t a, framepos_t b)
                return;
        }
 
+       framepos_t session_end_marker_shift_samples = session_end_shift * _nominal_frame_rate;
+
        if (_session_range_location == 0) {
 
-               add_session_range_location (a, b);
+               set_session_range_location (a, b + session_end_marker_shift_samples);
 
        } else {
 
@@ -3617,13 +4136,13 @@ Session::add_source (boost::shared_ptr<Source> source)
                /* yay, new source */
 
                boost::shared_ptr<FileSource> fs = boost::dynamic_pointer_cast<FileSource> (source);
-               
+
                if (fs) {
                        if (!fs->within_session()) {
                                ensure_search_path_includes (Glib::path_get_dirname (fs->path()), fs->type());
                        }
                }
-               
+
                set_dirty();
 
                boost::shared_ptr<AudioFileSource> afs;
@@ -3719,7 +4238,7 @@ Session::midi_source_by_path (const std::string& path) const
                        = boost::dynamic_pointer_cast<MidiSource>(s->second);
                boost::shared_ptr<FileSource> fs
                        = boost::dynamic_pointer_cast<FileSource>(s->second);
-               
+
                if (ms && fs && fs->path() == path) {
                        return ms;
                }
@@ -3746,20 +4265,31 @@ Session::count_sources_by_origin (const string& path)
        return cnt;
 }
 
+static string
+peak_file_helper (const string& peak_path, const string& file_path, const string& file_base, bool hash) {
+       if (hash) {
+               std::string checksum = Glib::Checksum::compute_checksum(Glib::Checksum::CHECKSUM_SHA1, file_path + G_DIR_SEPARATOR + file_base);
+               return Glib::build_filename (peak_path, checksum + peakfile_suffix);
+       } else {
+               return Glib::build_filename (peak_path, file_base + peakfile_suffix);
+       }
+}
+
 string
-Session::peak_path (string base) const
+Session::construct_peak_filepath (const string& filepath, const bool in_session, const bool old_peak_name) const
 {
-       if (Glib::path_is_absolute (base)) {
+       string interchange_dir_string = string (interchange_dir_name) + G_DIR_SEPARATOR;
+
+       if (Glib::path_is_absolute (filepath)) {
 
                /* rip the session dir from the audiofile source */
 
                string session_path;
-               string interchange_dir_string = string (interchange_dir_name) + G_DIR_SEPARATOR;
                bool in_another_session = true;
-               
-               if (base.find (interchange_dir_string) != string::npos) {
-               
-                       session_path = Glib::path_get_dirname (base); /* now ends in audiofiles */
+
+               if (filepath.find (interchange_dir_string) != string::npos) {
+
+                       session_path = Glib::path_get_dirname (filepath); /* now ends in audiofiles */
                        session_path = Glib::path_get_dirname (session_path); /* now ends in session name */
                        session_path = Glib::path_get_dirname (session_path); /* now ends in interchange */
                        session_path = Glib::path_get_dirname (session_path); /* now has session path */
@@ -3775,35 +4305,48 @@ Session::peak_path (string base) const
                } else {
                        in_another_session = false;
                }
-               
+
 
                if (in_another_session) {
                        SessionDirectory sd (session_path);
-                       return Glib::build_filename (sd.peak_path(), Glib::path_get_basename (base) + peakfile_suffix);
+                       return peak_file_helper (sd.peak_path(), "", Glib::path_get_basename (filepath), !old_peak_name);
                }
        }
 
-       base = Glib::path_get_basename (base);
-       return Glib::build_filename (_session_dir->peak_path(), base + peakfile_suffix);
+       /* 1) if file belongs to this session
+        * it may be a relative path (interchange/...)
+        * or just basename (session_state, remove source)
+        * -> just use the basename
+        */
+       std::string filename = Glib::path_get_basename (filepath);
+       std::string path;
+
+       /* 2) if the file is outside our session dir:
+        * (imported but not copied) add the path for check-summming */
+       if (!in_session) {
+               path = Glib::path_get_dirname (filepath);
+       }
+
+       return peak_file_helper (_session_dir->peak_path(), path, Glib::path_get_basename (filepath), !old_peak_name);
 }
 
 string
 Session::new_audio_source_path_for_embedded (const std::string& path)
 {
-       /* embedded source: 
+       /* embedded source:
         *
         * we know that the filename is already unique because it exists
-        * out in the filesystem. 
+        * out in the filesystem.
         *
         * However, when we bring it into the session, we could get a
         * collision.
         *
         * Eg. two embedded files:
-        * 
+        *
         *          /foo/bar/baz.wav
         *          /frob/nic/baz.wav
         *
-        * When merged into session, these collide. 
+        * When merged into session, these collide.
         *
         * There will not be a conflict with in-memory sources
         * because when the source was created we already picked
@@ -3817,7 +4360,7 @@ Session::new_audio_source_path_for_embedded (const std::string& path)
        SessionDirectory sdir (get_best_session_directory_for_new_audio());
        string base = Glib::path_get_basename (path);
        string newpath = Glib::build_filename (sdir.sound_path(), base);
-       
+
        if (Glib::file_test (newpath, Glib::FILE_TEST_EXISTS)) {
 
                MD5 md5;
@@ -3825,14 +4368,14 @@ Session::new_audio_source_path_for_embedded (const std::string& path)
                md5.digestString (path.c_str());
                md5.writeToString ();
                base = md5.digestChars;
-               
+
                string ext = get_suffix (path);
 
                if (!ext.empty()) {
                        base += '.';
                        base += ext;
                }
-               
+
                newpath = Glib::build_filename (sdir.sound_path(), base);
 
                /* if this collides, we're screwed */
@@ -3847,14 +4390,14 @@ Session::new_audio_source_path_for_embedded (const std::string& path)
        return newpath;
 }
 
-/** Return true if there are no audio file sources that use @param name as 
- * the filename component of their path. 
+/** Return true if there are no audio file sources that use @param name as
+ * the filename component of their path.
  *
  * Return false otherwise.
  *
- * This method MUST ONLY be used to check in-session, mono files since it 
+ * This method MUST ONLY be used to check in-session, mono files since it
  * hard-codes the channel of the audio file source we are looking for as zero.
- * 
+ *
  * If/when Ardour supports native files in non-mono formats, the logic here
  * will need to be revisited.
  */
@@ -3866,7 +4409,7 @@ Session::audio_source_name_is_unique (const string& name)
        uint32_t existing = 0;
 
        for (vector<string>::const_iterator i = sdirs.begin(); i != sdirs.end(); ++i) {
-               
+
                /* note that we search *without* the extension so that
                   we don't end up both "Audio 1-1.wav" and "Audio 1-1.caf"
                   in the event that this new name is required for
@@ -3874,12 +4417,12 @@ Session::audio_source_name_is_unique (const string& name)
                */
 
                const string spath = *i;
-               
+
                if (matching_unsuffixed_filename_exists_in (spath, name)) {
                        existing++;
                        break;
                }
-               
+
                /* it is possible that we have the path already
                 * assigned to a source that has not yet been written
                 * (ie. the write source for a diskstream). we have to
@@ -3888,8 +4431,8 @@ Session::audio_source_name_is_unique (const string& name)
                 * two Sources point to the same file with different
                 * notions of their removability.
                 */
-               
-               
+
+
                string possible_path = Glib::build_filename (spath, name);
 
                if (audio_source_by_path_and_channel (possible_path, 0)) {
@@ -3906,20 +4449,20 @@ Session::format_audio_source_name (const string& legalized_base, uint32_t nchan,
 {
        ostringstream sstr;
        const string ext = native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
-       
-       if (destructive) {
+
+       if (Profile->get_trx() && destructive) {
                sstr << 'T';
                sstr << setfill ('0') << setw (4) << cnt;
                sstr << legalized_base;
        } else {
                sstr << legalized_base;
-               
+
                if (take_required || related_exists) {
                        sstr << '-';
                        sstr << cnt;
                }
        }
-       
+
        if (nchan == 2) {
                if (chan == 0) {
                        sstr << "%L";
@@ -3936,7 +4479,7 @@ Session::format_audio_source_name (const string& legalized_base, uint32_t nchan,
                        sstr << chan+1;
                }
        }
-       
+
        sstr << ext;
 
        return sstr.str();
@@ -3959,11 +4502,11 @@ Session::new_audio_source_path (const string& base, uint32_t nchan, uint32_t cha
        for (cnt = (destructive ? ++destructive_index : 1); cnt <= limit; ++cnt) {
 
                possible_name = format_audio_source_name (legalized, nchan, chan, destructive, take_required, cnt, some_related_source_name_exists);
-               
+
                if (audio_source_name_is_unique (possible_name)) {
                        break;
                }
-               
+
                some_related_source_name_exists = true;
 
                if (cnt > limit) {
@@ -4018,14 +4561,14 @@ Session::new_midi_source_path (const string& base)
 
                vector<space_and_path>::iterator i;
                uint32_t existing = 0;
-               
+
                for (vector<string>::const_iterator i = sdirs.begin(); i != sdirs.end(); ++i) {
 
                        snprintf (buf, sizeof(buf), "%s-%u.mid", legalized.c_str(), cnt);
                        possible_name = buf;
 
                        possible_path = Glib::build_filename (*i, possible_name);
-                       
+
                        if (Glib::file_test (possible_path, Glib::FILE_TEST_EXISTS)) {
                                existing++;
                        }
@@ -4064,7 +4607,7 @@ Session::create_audio_source_for_session (size_t n_chans, string const & base, u
 
        if (!path.empty()) {
                return boost::dynamic_pointer_cast<AudioFileSource> (
-                       SourceFactory::createWritable (DataType::AUDIO, *this, path, destructive, frame_rate()));
+                       SourceFactory::createWritable (DataType::AUDIO, *this, path, destructive, frame_rate(), true, true));
        } else {
                throw failed_constructor ();
        }
@@ -4075,7 +4618,7 @@ boost::shared_ptr<MidiSource>
 Session::create_midi_source_for_session (string const & basic_name)
 {
        const string path = new_midi_source_path (basic_name);
-       
+
        if (!path.empty()) {
                return boost::dynamic_pointer_cast<SMFSource> (
                        SourceFactory::createWritable (
@@ -4090,24 +4633,24 @@ boost::shared_ptr<MidiSource>
 Session::create_midi_source_by_stealing_name (boost::shared_ptr<Track> track)
 {
        /* the caller passes in the track the source will be used in,
-          so that we can keep the numbering sane. 
-          
+          so that we can keep the numbering sane.
+
           Rationale: a track with the name "Foo" that has had N
           captures carried out so far will ALREADY have a write source
           named "Foo-N+1.mid" waiting to be used for the next capture.
-          
+
           If we call new_midi_source_name() we will get "Foo-N+2". But
           there is no region corresponding to "Foo-N+1", so when
           "Foo-N+2" appears in the track, the gap presents the user
           with odd behaviour - why did it skip past Foo-N+1?
-          
+
           We could explain this to the user in some odd way, but
           instead we rename "Foo-N+1.mid" as "Foo-N+2.mid", and then
           use "Foo-N+1" here.
-          
+
           If that attempted rename fails, we get "Foo-N+2.mid" anyway.
        */
-       
+
        boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (track);
        assert (mt);
        std::string name = track->steal_write_source_name ();
@@ -4237,7 +4780,7 @@ Session::graph_reordered ()
           from a set_state() call or creating new tracks. Ditto for deletion.
        */
 
-       if ((_state_of_the_state & (InitialConnecting|Deletion)) || _adding_routes_in_progress) {
+       if ((_state_of_the_state & (InitialConnecting|Deletion)) || _adding_routes_in_progress || _reconnecting_routes_in_progress || _route_deletion_in_progress) {
                return;
        }
 
@@ -4273,7 +4816,7 @@ Session::available_capture_duration ()
        if (_total_free_4k_blocks_uncertain) {
                return boost::optional<framecnt_t> ();
        }
-       
+
        float sample_bytes_on_disk = 4.0; // keep gcc happy
 
        switch (config.get_native_file_data_format()) {
@@ -4560,12 +5103,12 @@ void
 Session::reset_native_file_format ()
 {
        boost::shared_ptr<RouteList> rl = routes.reader ();
+
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
                boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
                if (tr) {
                        /* don't save state as we do this, there's no point
                         */
-
                        _state_of_the_state = StateOfTheState (_state_of_the_state|InCleanup);
                        tr->reset_write_sources (false);
                        _state_of_the_state = StateOfTheState (_state_of_the_state & ~InCleanup);
@@ -4624,7 +5167,7 @@ Session::freeze_all (InterThreadInfo& itt)
 boost::shared_ptr<Region>
 Session::write_one_track (Track& track, framepos_t start, framepos_t end,
                          bool /*overwrite*/, vector<boost::shared_ptr<Source> >& srcs,
-                         InterThreadInfo& itt, 
+                         InterThreadInfo& itt,
                          boost::shared_ptr<Processor> endpoint, bool include_endpoint,
                          bool for_export, bool for_freeze)
 {
@@ -4685,7 +5228,7 @@ Session::write_one_track (Track& track, framepos_t start, framepos_t end,
                string path = ((track.data_type() == DataType::AUDIO)
                               ? new_audio_source_path (legal_playlist_name, diskstream_channels.n_audio(), chan_n, false, true)
                               : new_midi_source_path (legal_playlist_name));
-               
+
                if (path.empty()) {
                        goto out;
                }
@@ -4948,9 +5491,15 @@ Session::have_rec_enabled_track () const
        return g_atomic_int_get (const_cast<gint*>(&_have_rec_enabled_track)) == 1;
 }
 
+bool
+Session::have_rec_disabled_track () const
+{
+    return g_atomic_int_get (const_cast<gint*>(&_have_rec_disabled_track)) == 1;
+}
+
 /** Update the state of our rec-enabled tracks flag */
 void
-Session::update_have_rec_enabled_track ()
+Session::update_route_record_state ()
 {
        boost::shared_ptr<RouteList> rl = routes.reader ();
        RouteList::iterator i = rl->begin();
@@ -4971,6 +5520,22 @@ Session::update_have_rec_enabled_track ()
        if (g_atomic_int_get (&_have_rec_enabled_track) != old) {
                RecordStateChanged (); /* EMIT SIGNAL */
        }
+
+       for (i = rl->begin(); i != rl->end (); ++i) {
+               boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
+               if (tr && !tr->record_enabled ()) {
+                       break;
+               }
+       }
+
+       g_atomic_int_set (&_have_rec_disabled_track, i != rl->end () ? 1 : 0);
+
+       bool record_arm_state_changed = (old != g_atomic_int_get (&_have_rec_enabled_track) );
+
+       if (record_status() == Recording && record_arm_state_changed ) {
+               RecordArmStateChanged ();
+       }
+
 }
 
 void
@@ -5013,7 +5578,8 @@ Session::route_added_to_route_group (RouteGroup* rg, boost::weak_ptr<Route> r)
 void
 Session::route_removed_from_route_group (RouteGroup* rg, boost::weak_ptr<Route> r)
 {
-       RouteRemovedFromRouteGroup (rg, r);
+       update_route_record_state ();
+       RouteRemovedFromRouteGroup (rg, r); /* EMIT SIGNAL */
 }
 
 boost::shared_ptr<RouteList>
@@ -5090,7 +5656,7 @@ Session::current_end_frame () const
 }
 
 void
-Session::add_session_range_location (framepos_t start, framepos_t end)
+Session::set_session_range_location (framepos_t start, framepos_t end)
 {
        _session_range_location = new Location (*this, start, end, _("session"), Location::IsSessionRange);
        _locations->add (_session_range_location);
@@ -5483,7 +6049,7 @@ Session::update_latency_compensation (bool force_whole_graph)
                                                     (some_track_latency_changed ? "yes" : "no")));
 
        DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n");
-       
+
        if (some_track_latency_changed || force_whole_graph)  {
                _engine.update_latencies ();
        }
@@ -5512,7 +6078,7 @@ Session::session_name_is_legal (const string& path)
        return 0;
 }
 
-uint32_t 
+uint32_t
 Session::next_control_id () const
 {
        int subtract = 0;
@@ -5526,6 +6092,12 @@ Session::next_control_id () const
                subtract++;
        }
 
+       /* the same about masterbus in Waves Tracks */
+
+       if (Profile->get_trx() && _master_out) {
+               subtract++;
+       }
+
        return nroutes() - subtract;
 }
 
@@ -5543,6 +6115,14 @@ Session::notify_remote_id_change ()
        default:
                break;
        }
+
+#ifdef USE_TRACKS_CODE_FEATURES
+               /* Waves Tracks: for Waves Tracks session it's required to reconnect their IOs
+                * if track order has been changed by user
+                */
+               reconnect_existing_routes(true, true);
+#endif
+
 }
 
 void
@@ -5597,6 +6177,11 @@ Session::reconnect_ltc_input ()
                if (src != _("None") && !src.empty())  {
                        _ltc_input->nth (0)->connect (src);
                }
+
+               if ( ARDOUR::Profile->get_trx () ) {
+                       // Tracks need this signal to update timecode_source_dropdown
+                       MtcOrLtcInputPortChanged (); //emit signal
+               }
        }
 }
 
@@ -5605,14 +6190,48 @@ Session::reconnect_ltc_output ()
 {
        if (_ltc_output) {
 
-#if 0
-               string src = Config->get_ltc_sink_port();
+               string src = Config->get_ltc_output_port();
 
                _ltc_output->disconnect (this);
 
                if (src != _("None") && !src.empty())  {
                        _ltc_output->nth (0)->connect (src);
                }
-#endif
        }
 }
+
+void
+Session::set_range_selection (framepos_t start, framepos_t end)
+{
+       _range_selection = Evoral::Range<framepos_t> (start, end);
+#ifdef USE_TRACKS_CODE_FEATURES
+       follow_playhead_priority ();
+#endif
+}
+
+void
+Session::set_object_selection (framepos_t start, framepos_t end)
+{
+       _object_selection = Evoral::Range<framepos_t> (start, end);
+#ifdef USE_TRACKS_CODE_FEATURES
+       follow_playhead_priority ();
+#endif
+}
+
+void
+Session::clear_range_selection ()
+{
+       _range_selection = Evoral::Range<framepos_t> (-1,-1);
+#ifdef USE_TRACKS_CODE_FEATURES
+       follow_playhead_priority ();
+#endif
+}
+
+void
+Session::clear_object_selection ()
+{
+       _object_selection = Evoral::Range<framepos_t> (-1,-1);
+#ifdef USE_TRACKS_CODE_FEATURES
+       follow_playhead_priority ();
+#endif
+}