Merge branch 'master' into windows+cc
[ardour.git] / libs / ardour / session.cc
index ecdd9bca8d5a846cdcfc8ed818b1d38c12df7e28..4b30543cb018021dfd904314d89819926b4a194f 100644 (file)
@@ -30,7 +30,7 @@
 #include <unistd.h>
 #include <limits.h>
 
-#include <glibmm/thread.h>
+#include <glibmm/threads.h>
 #include <glibmm/miscutils.h>
 #include <glibmm/fileutils.h>
 
 #include "pbd/stacktrace.h"
 #include "pbd/file_utils.h"
 #include "pbd/convert.h"
-#include "pbd/strsplit.h"
+#include "pbd/unwind.h"
+#include "pbd/search_path.h"
 
 #include "ardour/amp.h"
 #include "ardour/analyser.h"
+#include "ardour/async_midi_port.h"
 #include "ardour/audio_buffer.h"
 #include "ardour/audio_diskstream.h"
 #include "ardour/audio_port.h"
 #include "ardour/audio_track.h"
 #include "ardour/audioengine.h"
 #include "ardour/audiofilesource.h"
-#include "ardour/audioplaylist.h"
-#include "ardour/audioregion.h"
 #include "ardour/auditioner.h"
 #include "ardour/buffer_manager.h"
 #include "ardour/buffer_set.h"
 #include "ardour/bundle.h"
 #include "ardour/butler.h"
 #include "ardour/click.h"
-#include "ardour/configuration.h"
 #include "ardour/control_protocol_manager.h"
-#include "ardour/crossfade.h"
-#include "ardour/cycle_timer.h"
 #include "ardour/data_type.h"
 #include "ardour/debug.h"
 #include "ardour/filename_extensions.h"
-#include "ardour/internal_send.h"
-#include "ardour/io_processor.h"
-#include "ardour/midi_diskstream.h"
-#include "ardour/midi_playlist.h"
-#include "ardour/midi_region.h"
+#include "ardour/graph.h"
+#include "ardour/midiport_manager.h"
 #include "ardour/midi_track.h"
 #include "ardour/midi_ui.h"
-#include "ardour/named_selection.h"
-#include "ardour/process_thread.h"
+#include "ardour/operations.h"
 #include "ardour/playlist.h"
+#include "ardour/plugin.h"
 #include "ardour/plugin_insert.h"
-#include "ardour/port_insert.h"
-#include "ardour/processor.h"
+#include "ardour/process_thread.h"
 #include "ardour/rc_configuration.h"
 #include "ardour/recent_sessions.h"
+#include "ardour/region.h"
 #include "ardour/region_factory.h"
-#include "ardour/return.h"
+#include "ardour/route_graph.h"
 #include "ardour/route_group.h"
 #include "ardour/send.h"
 #include "ardour/session.h"
 #include "ardour/session_directory.h"
-#include "ardour/session_directory.h"
-#include "ardour/session_metadata.h"
 #include "ardour/session_playlists.h"
-#include "ardour/slave.h"
 #include "ardour/smf_source.h"
 #include "ardour/source_factory.h"
-#include "ardour/tape_file_matcher.h"
-#include "ardour/tempo.h"
-#include "ardour/utils.h"
-#include "ardour/graph.h"
 #include "ardour/speakers.h"
-#include "ardour/operations.h"
+#include "ardour/utils.h"
 
 #include "midi++/port.h"
 #include "midi++/mmc.h"
-#include "midi++/manager.h"
 
 #include "i18n.h"
 
+namespace ARDOUR {
+class MidiSource;
+class Processor;
+class Speakers;
+}
+
 using namespace std;
 using namespace ARDOUR;
 using namespace PBD;
 
 bool Session::_disable_all_loaded_plugins = false;
 
+PBD::Signal1<int,uint32_t> Session::AudioEngineSetupRequired;
 PBD::Signal1<void,std::string> Session::Dialog;
 PBD::Signal0<int> Session::AskAboutPendingState;
 PBD::Signal2<int, framecnt_t, framecnt_t> Session::AskAboutSampleRateMismatch;
@@ -123,76 +116,211 @@ PBD::Signal3<int,Session*,std::string,DataType> Session::MissingFile;
 
 PBD::Signal1<void, framepos_t> Session::StartTimeChanged;
 PBD::Signal1<void, framepos_t> Session::EndTimeChanged;
-PBD::Signal0<void> Session::AutoBindingOn;
-PBD::Signal0<void> Session::AutoBindingOff;
 PBD::Signal2<void,std::string, std::string> Session::Exported;
 PBD::Signal1<int,boost::shared_ptr<Playlist> > Session::AskAboutPlaylistDeletion;
 PBD::Signal0<void> Session::Quit;
+PBD::Signal0<void> Session::FeedbackDetected;
+PBD::Signal0<void> Session::SuccessfulGraphSort;
+PBD::Signal2<void,std::string,std::string> Session::VersionMismatch;
 
 static void clean_up_session_event (SessionEvent* ev) { delete ev; }
 const SessionEvent::RTeventCallback Session::rt_cleanup (clean_up_session_event);
 
+/** @param snapshot_name Snapshot name, without .ardour suffix */
 Session::Session (AudioEngine &eng,
                   const string& fullpath,
                   const string& snapshot_name,
                   BusProfile* bus_profile,
                   string mix_template)
-       : _engine (eng)
+       : playlists (new SessionPlaylists)
+       , _engine (eng)
+       , process_function (&Session::process_with_events)
+       , waiting_for_sync_offset (false)
+       , _base_frame_rate (0)
+       , _current_frame_rate (0)
+       , _nominal_frame_rate (0)
+       , transport_sub_state (0)
+       , _record_status (Disabled)
+       , _transport_frame (0)
+       , _session_range_location (0)
+       , _slave (0)
+       , _silent (false)
+       , _transport_speed (0)
+       , _default_transport_speed (1.0)
+       , _last_transport_speed (0)
        , _target_transport_speed (0.0)
+       , auto_play_legal (false)
+       , _last_slave_transport_frame (0)
+       , maximum_output_latency (0)
        , _requested_return_frame (-1)
-       , _session_dir (new SessionDirectory(fullpath))
+       , current_block_size (0)
+       , _worst_output_latency (0)
+       , _worst_input_latency (0)
+       , _worst_track_latency (0)
+       , _have_captured (false)
+       , _meter_hold (0)
+       , _meter_falloff (0)
+       , _non_soloed_outs_muted (false)
+       , _listen_cnt (0)
+       , _solo_isolated_cnt (0)
+       , _writable (false)
+       , _was_seamless (Config->get_seamless_loop ())
+       , _under_nsm_control (false)
+       , delta_accumulator_cnt (0)
+       , average_slave_delta (1800) // !!! why 1800 ???
+       , average_dir (0)
+       , have_first_delta_accumulator (false)
+       , _slave_state (Stopped)
+       , post_export_sync (false)
+       , post_export_position (0)
+       , _exporting (false)
+       , _export_started (false)
+       , _export_rolling (false)
+       , _pre_export_mmc_enabled (false)
+       , _name (snapshot_name)
+       , _is_new (true)
+       , _send_qf_mtc (false)
+       , _pframes_since_last_mtc (0)
+       , session_midi_feedback (0)
+       , play_loop (false)
+       , loop_changing (false)
+       , last_loopend (0)
+       , _session_dir (new SessionDirectory (fullpath))
+       , _current_snapshot_name (snapshot_name)          
        , state_tree (0)
-       , _state_of_the_state (Clean)
+       , state_was_pending (false)
+       , _state_of_the_state (StateOfTheState(CannotSave|InitialConnecting|Loading))
+       , _last_roll_location (0)
+       , _last_roll_or_reversal_location (0)
+       , _last_record_location (0)
+       , pending_locate_roll (false)
+       , pending_locate_frame (0)
+       , pending_locate_flush (false)
+       , pending_abort (false)
+       , pending_auto_loop (false)
        , _butler (new Butler (*this))
        , _post_transport_work (0)
+       ,  cumulative_rf_motion (0)
+       , rf_scale (1.0)
+       , _locations (new Locations (*this))
+       , step_speed (0)
+       , outbound_mtc_timecode_frame (0)
+       , next_quarter_frame_to_send (-1)
+       , _frames_per_timecode_frame (0)
+       , _frames_per_hour (0)
+       , _timecode_frames_per_hour (0)
+       , last_timecode_valid (false)
+       , last_timecode_when (0)
        , _send_timecode_update (false)
+       , ltc_encoder (0)
+       , ltc_enc_buf(0)
+       , ltc_buf_off (0)
+       , ltc_buf_len (0)
+       , ltc_speed (0)
+       , ltc_enc_byte (0)
+       , ltc_enc_pos (0)
+       , ltc_enc_cnt (0)
+       , ltc_enc_off (0)
+       , restarting (false)
+       , ltc_prev_cycle (0)
+       , ltc_timecode_offset (0)
+       , ltc_timecode_negative_offset (false)
+       , midi_control_ui (0)
+       , _tempo_map (0)
        , _all_route_group (new RouteGroup (*this, "all"))
-       , route_graph (new Graph(*this))
        , routes (new RouteList)
+       , _adding_routes_in_progress (false)
+       , destructive_index (0)
+       , solo_update_disabled (false)
+       , default_fade_steepness (0)
+       , default_fade_msecs (0)
        , _total_free_4k_blocks (0)
+       , _total_free_4k_blocks_uncertain (false)
+       , no_questions_about_missing_files (false)
+       , _playback_load (0)
+       , _capture_load (0)
        , _bundles (new BundleList)
        , _bundle_xml_node (0)
        , _current_trans (0)
-       , _click_io ((IO*) 0)
+       , _clicking (false)
        , click_data (0)
        , click_emphasis_data (0)
+       , click_length (0)
+       , click_emphasis_length (0)
+       , _clicks_cleared (0)
+       , _play_range (false)
        , main_outs (0)
-       , _metadata (new SessionMetadata())
+       , first_file_data_format_reset (true)
+       , first_file_header_format_reset (true)
+       , have_looped (false)
        , _have_rec_enabled_track (false)
+       , _step_editors (0)
        , _suspend_timecode_transmission (0)
+       ,  _speakers (new Speakers)
+       , ignore_route_processor_changes (false)
+       , _midi_ports (0)
+       , _mmc (0)
 {
-       _locations = new Locations (*this);
-
-       playlists.reset (new SessionPlaylists);
+       uint32_t sr = 0;
 
-       _all_route_group->set_active (true, this);
+       pre_engine_init (fullpath);
+       
+       if (_is_new) {
+               if (ensure_engine (sr)) {
+                       destroy ();
+                       throw failed_constructor ();
+               }
 
-       interpolation.add_channel_to (0, 0);
+               if (create (mix_template, bus_profile)) {
+                       destroy ();
+                       throw failed_constructor ();
+               }
 
-       if (!eng.connected()) {
-               throw failed_constructor();
-       }
+               /* if a mix template was provided, then ::create() will
+                * have copied it into the session and we need to load it
+                * so that we have the state ready for ::set_state()
+                * after the engine is started.
+                *
+                * Note that we do NOT try to get the sample rate from
+                * the template at this time, though doing so would
+                * be easy if we decided this was an appropriate part
+                * of a template.
+                */
 
-       n_physical_outputs = _engine.n_physical_outputs ();
-       n_physical_inputs =  _engine.n_physical_inputs ();
+               if (!mix_template.empty() && load_state (_current_snapshot_name)) {
+                       throw failed_constructor ();
+               }
 
-       first_stage_init (fullpath, snapshot_name);
+       } else {
 
-       _is_new = !Glib::file_test (_path, Glib::FileTest (G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR));
+               if (load_state (_current_snapshot_name)) {
+                       throw failed_constructor ();
+               }
+       
+               /* try to get sample rate from XML state so that we
+                * can influence the SR if we set up the audio
+                * engine.
+                */
+
+               if (state_tree) {
+                       const XMLProperty* prop;
+                       if ((prop = state_tree->root()->property (X_("sample-rate"))) != 0) {           
+                               sr = atoi (prop->value());
+                       }
+               }
 
-       if (_is_new) {
-               if (create (mix_template, bus_profile)) {
+               if (ensure_engine (sr)) {
                        destroy ();
                        throw failed_constructor ();
                }
        }
 
-       if (second_stage_init ()) {
+       if (post_engine_init ()) {
                destroy ();
                throw failed_constructor ();
        }
 
-       store_recent_sessions(_name, _path);
+       store_recent_sessions (_name, _path);
 
        bool was_dirty = dirty();
 
@@ -209,13 +337,101 @@ Session::Session (AudioEngine &eng,
        EndTimeChanged.connect_same_thread (*this, boost::bind (&Session::end_time_changed, this, _1));
 
        _is_new = false;
+
+       /* hook us up to the engine since we are now completely constructed */
+
+       BootMessage (_("Connect to engine"));
+
+       _engine.set_session (this);
+       _engine.reset_timebase ();
+
+       BootMessage (_("Session loading complete"));
+
 }
 
 Session::~Session ()
 {
+#ifdef PT_TIMING       
+       ST.dump ("ST.dump");
+#endif 
        destroy ();
 }
 
+int
+Session::ensure_engine (uint32_t desired_sample_rate)
+{
+       if (_engine.current_backend() == 0) {
+               /* backend is unknown ... */
+               boost::optional<int> r = AudioEngineSetupRequired (desired_sample_rate);
+               if (r.get_value_or (-1) != 0) {
+                       return -1;
+               }
+       } else if (_engine.setup_required()) {
+               /* backend is known, but setup is needed */
+               boost::optional<int> r = AudioEngineSetupRequired (desired_sample_rate);
+               if (r.get_value_or (-1) != 0) {
+                       return -1;
+               }
+       } else if (!_engine.running()) {
+               if (_engine.start()) {
+                       return -1;
+               }
+       }
+
+       /* at this point the engine should be running
+       */
+
+       if (!_engine.running()) {
+               return -1;
+       }
+
+       return immediately_post_engine ();
+
+}
+
+int
+Session::immediately_post_engine ()
+{
+       /* Do various initializations that should take place directly after we
+        * 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.
+               */
+               _process_graph.reset (new Graph (*this));
+       }
+
+       /* every time we reconnect, recompute worst case output latencies */
+
+       _engine.Running.connect_same_thread (*this, boost::bind (&Session::initialize_latencies, this));
+
+       if (synced_to_engine()) {
+               _engine.transport_stop ();
+       }
+
+       if (config.get_jack_time_master()) {
+               _engine.transport_locate (_transport_frame);
+       }
+
+       try {
+               BootMessage (_("Set up LTC"));
+               setup_ltc ();
+               BootMessage (_("Set up Click"));
+               setup_click ();
+               BootMessage (_("Set up standard connections"));
+               setup_bundles ();
+       }
+
+       catch (failed_constructor& err) {
+               return -1;
+       }
+
+       return 0;
+}
+
 void
 Session::destroy ()
 {
@@ -229,8 +445,20 @@ Session::destroy ()
 
        _state_of_the_state = StateOfTheState (CannotSave|Deletion);
 
+       /* disconnect from any and all signals that we are connected to */
+
+       drop_connections ();
+
        _engine.remove_session ();
 
+       /* deregister all ports - there will be no process or any other
+        * callbacks from the engine any more.
+        */
+
+       Port::PortDrop (); /* EMIT SIGNAL */
+
+       ltc_tx_cleanup();
+
        /* clear history so that no references to objects are held any more */
 
        _history.clear ();
@@ -245,6 +473,8 @@ Session::destroy ()
 
        _butler->drop_references ();
        delete _butler;
+       _butler = 0;
+       
        delete midi_control_ui;
        delete _all_route_group;
 
@@ -270,9 +500,6 @@ Session::destroy ()
 
        /* tell everyone to drop references and delete objects as we go */
 
-       DEBUG_TRACE (DEBUG::Destruction, "delete named selections\n");
-       named_selections.clear ();
-
        DEBUG_TRACE (DEBUG::Destruction, "delete regions\n");
        RegionFactory::delete_all_regions ();
 
@@ -312,12 +539,12 @@ Session::destroy ()
                delete *i;
        }
 
-       Crossfade::set_buffer_size (0);
-
        /* not strictly necessary, but doing it here allows the shared_ptr debugging to work */
        playlists.reset ();
 
-       delete _locations;
+       delete _mmc; _mmc = 0;
+       delete _midi_ports; _midi_ports = 0;
+       delete _locations; _locations = 0;
 
        DEBUG_TRACE (DEBUG::Destruction, "Session::destroy() done\n");
 
@@ -327,97 +554,110 @@ Session::destroy ()
 }
 
 void
-Session::when_engine_running ()
+Session::setup_ltc ()
 {
-       string first_physical_output;
-
-       BootMessage (_("Set block size and sample rate"));
-
-       set_block_size (_engine.frames_per_cycle());
-       set_frame_rate (_engine.frame_rate());
-
-       BootMessage (_("Using configuration"));
-
-       boost::function<void (std::string)> ff (boost::bind (&Session::config_changed, this, _1, false));
-       boost::function<void (std::string)> ft (boost::bind (&Session::config_changed, this, _1, true));
-
-       Config->map_parameters (ff);
-       config.map_parameters (ft);
-
-       /* every time we reconnect, recompute worst case output latencies */
-
-       _engine.Running.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies, this));
-
-       if (synced_to_jack()) {
-               _engine.transport_stop ();
+       XMLNode* child = 0;
+       
+       _ltc_input.reset (new IO (*this, _("LTC In"), IO::Input));
+       _ltc_output.reset (new IO (*this, _("LTC Out"), IO::Output));
+       
+       if (state_tree && (child = find_named_node (*state_tree->root(), "LTC-In")) != 0) {
+               _ltc_input->set_state (*(child->children().front()), Stateful::loading_state_version);
+       } else {
+               {
+                       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                       _ltc_input->ensure_io (ChanCount (DataType::AUDIO, 1), true, this);
+               }
+               reconnect_ltc_input ();
        }
-
-       if (config.get_jack_time_master()) {
-               _engine.transport_locate (_transport_frame);
+       
+       if (state_tree && (child = find_named_node (*state_tree->root(), "LTC-Out")) != 0) {
+               _ltc_output->set_state (*(child->children().front()), Stateful::loading_state_version);
+       } else {
+               {
+                       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                       _ltc_output->ensure_io (ChanCount (DataType::AUDIO, 1), true, this);
+               }
+               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 (_("LTC-in"));
+       _ltc_output->nth (0)->set_name (_("LTC-out"));
+}
 
+void
+Session::setup_click ()
+{
        _clicking = false;
+       _click_io.reset (new ClickIO (*this, "click"));
+       _click_gain.reset (new Amp (*this));
+       _click_gain->activate ();
+       if (state_tree) {
+               setup_click_state (*state_tree->root());
+       }
+}
 
-       try {
-               XMLNode* child = 0;
-
-               _click_io.reset (new ClickIO (*this, "click"));
-
-               if (state_tree && (child = find_named_node (*state_tree->root(), "Click")) != 0) {
+void
+Session::setup_click_state (const XMLNode& node)
+{      
+       const XMLNode* child = 0;
 
-                       /* existing state for Click */
-                       int c;
+       if ((child = find_named_node (node, "Click")) != 0) {
+               
+               /* existing state for Click */
+               int c = 0;
 
-                       if (Stateful::loading_state_version < 3000) {
-                               c = _click_io->set_state_2X (*child->children().front(), Stateful::loading_state_version, false);
-                       } else {
-                               c = _click_io->set_state (*child->children().front(), Stateful::loading_state_version);
+               if (Stateful::loading_state_version < 3000) {
+                       c = _click_io->set_state_2X (*child->children().front(), Stateful::loading_state_version, false);
+               } else {
+                       const XMLNodeList& children (child->children());
+                       XMLNodeList::const_iterator i = children.begin();
+                       if ((c = _click_io->set_state (**i, Stateful::loading_state_version)) == 0) {
+                               ++i;
+                               if (i != children.end()) {
+                                       c = _click_gain->set_state (**i, Stateful::loading_state_version);
+                               }
                        }
+               }
+                       
+               if (c == 0) {
+                       _clicking = Config->get_clicking ();
 
+               } else {
 
-                       if (c == 0) {
-                               _clicking = Config->get_clicking ();
-
-                       } else {
-
-                               error << _("could not setup Click I/O") << endmsg;
-                               _clicking = false;
-                       }
+                       error << _("could not setup Click I/O") << endmsg;
+                       _clicking = false;
+               }
 
 
-               } else {
+       } else {
 
-                       /* default state for Click: dual-mono to first 2 physical outputs */
+               /* default state for Click: dual-mono to first 2 physical outputs */
 
-                       vector<string> outs;
-                       _engine.get_physical_outputs (DataType::AUDIO, outs);
+               vector<string> outs;
+               _engine.get_physical_outputs (DataType::AUDIO, outs);
 
-                       for (uint32_t physport = 0; physport < 2; ++physport) {
-                               if (outs.size() > physport) {
-                                       if (_click_io->add_port (outs[physport], this)) {
-                                               // relax, even though its an error
-                                       }
+               for (uint32_t physport = 0; physport < 2; ++physport) {
+                       if (outs.size() > physport) {
+                               if (_click_io->add_port (outs[physport], this)) {
+                                       // relax, even though its an error
                                }
                        }
-
-                       if (_click_io->n_ports () > ChanCount::ZERO) {
-                               _clicking = Config->get_clicking ();
-                       }
                }
-       }
 
-       catch (failed_constructor& err) {
-               error << _("cannot setup Click I/O") << endmsg;
-       }
-
-       BootMessage (_("Compute I/O Latencies"));
-
-       if (_clicking) {
-               // XXX HOW TO ALERT UI TO THIS ? DO WE NEED TO?
+               if (_click_io->n_ports () > ChanCount::ZERO) {
+                       _clicking = Config->get_clicking ();
+               }
        }
+}
 
-       BootMessage (_("Set up standard connections"));
-
+void
+Session::setup_bundles ()
+{
        vector<string> inputs[DataType::num_types];
        vector<string> outputs[DataType::num_types];
        for (uint32_t i = 0; i < DataType::num_types; ++i) {
@@ -516,136 +756,226 @@ Session::when_engine_running ()
                add_bundle (c);
        }
 
-       BootMessage (_("Setup signal flow and plugins"));
+}
 
-       ControlProtocolManager::instance().set_session (this);
+void
+Session::auto_connect_master_bus ()
+{
+       if (!_master_out || !Config->get_auto_connect_standard_busses() || _monitor_out) {
+               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)
+                                     << endmsg;
+                               break;
+                       }
+               }
+       }
+}
 
-       /* This must be done after the ControlProtocolManager set_session above,
-          as it will set states for ports which the ControlProtocolManager creates.
-       */
-       MIDI::Manager::instance()->set_port_states (Config->midi_port_states ());
+void
+Session::remove_monitor_section ()
+{
+       if (!_monitor_out) {
+               return;
+       }
 
-       /* And this must be done after the MIDI::Manager::set_port_states as
-        * it will try to make connections whose details are loaded by set_port_states.
-        */
+       /* force reversion to Solo-In-Place */
+       Config->set_solo_control_is_listen_control (false);
 
-       hookup_io ();
+       {
+               /* 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()) {
+                               /* relax */
+                       } else {
+                               (*x)->remove_aux_or_listen (_monitor_out);
+                       }
+               }
+       }
 
-       if (_is_new && !no_auto_connect()) {
+       remove_route (_monitor_out);
+       auto_connect_master_bus ();
+}
 
-               Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock());
+void
+Session::add_monitor_section ()
+{
+       RouteList rl;
 
-               /* don't connect the master bus outputs if there is a monitor bus */
+       if (_monitor_out || !_master_out) {
+               return;
+       }
 
-               if (_master_out && Config->get_auto_connect_standard_busses() && !_monitor_out) {
+       boost::shared_ptr<Route> r (new Route (*this, _("monitor"), Route::MonitorOut, DataType::AUDIO));
 
-                       /* if requested auto-connect the outputs to the first N physical ports.
-                        */
+       if (r->init ()) {
+               return;
+       }
 
-                       uint32_t limit = _master_out->n_outputs().n_total();
+#ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
+       // boost_debug_shared_ptr_mark_interesting (r.get(), "Route");
+#endif
+       {
+               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);
+       }
 
-                       for (uint32_t n = 0; n < limit; ++n) {
-                               Port* p = _master_out->output()->nth (n);
-                               string connect_to;
-                               if (outputs[p->type()].size() > n) {
-                                       connect_to = outputs[p->type()][n];
-                               }
+       rl.push_back (r);
+       add_routes (rl, false, false, false);
+       
+       assert (_monitor_out);
 
-                               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)
-                                                     << endmsg;
-                                               break;
-                                       }
+       /* 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
+                * conditionally ignore either the internal sends or the normal
+                * input feed, but we should really find a better way to do
+                * this, i think.
+                */
+
+               _master_out->output()->disconnect (this);
+
+               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)) {
+                                       error << string_compose (_("cannot connect control input %1 to %2"), n, connect_to)
+                                             << endmsg;
+                                       break;
                                }
                        }
                }
+       }
+       
+       /* 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 {
+                               warning << string_compose (_("The preferred I/O for the monitor bus (%1) cannot be found"),
+                                                          Config->get_monitor_bus_preferred_bundle())
+                                       << endmsg;
+                       }
+                       
+               } else {
+                       
+                       /* Monitor bus is audio only */
 
-               if (_monitor_out) {
-
-                       /* AUDIO ONLY as of june 29th 2009, because listen semantics for anything else
-                          are undefined, at best.
-                        */
-
-                       /* control out listens to master bus (but ignores it
-                          under some conditions)
-                       */
+                       vector<string> outputs[DataType::num_types];
 
-                       uint32_t limit = _monitor_out->n_inputs().n_audio();
+                       for (uint32_t i = 0; i < DataType::num_types; ++i) {
+                               _engine.get_physical_outputs (DataType (DataType::Symbol (i)), outputs[i]);
+                       }
 
-                       if (_master_out) {
+                       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) {
-                                       AudioPort* p = _monitor_out->input()->ports().nth_audio_port (n);
-                                       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)) {
-                                                       error << string_compose (_("cannot connect control input %1 to %2"), n, connect_to)
+                                       
+                                       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 (
+                                                               _("cannot connect control output %1 to %2"),
+                                                               n, connect_to)
                                                              << endmsg;
                                                        break;
                                                }
                                        }
                                }
                        }
+               }
+       }
 
-                       /* if control out is not connected, connect control out to physical outs
-                       */
-
-                       if (!_monitor_out->output()->connected ()) {
+       /* 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 ());
 
-                               if (!Config->get_monitor_bus_preferred_bundle().empty()) {
+       /* 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<Bundle> b = bundle_by_name (Config->get_monitor_bus_preferred_bundle());
 
-                                       if (b) {
-                                               _monitor_out->output()->connect_ports_to_bundle (b, this);
-                                       } else {
-                                               warning << string_compose (_("The preferred I/O for the monitor bus (%1) cannot be found"),
-                                                                          Config->get_monitor_bus_preferred_bundle())
-                                                       << endmsg;
-                                       }
+       boost::shared_ptr<RouteList> rls = routes.reader ();
 
-                               } else {
+       PBD::Unwinder<bool> uw (ignore_route_processor_changes, true);
 
-                                       /* Monitor bus is audio only */
-                                       uint32_t mod = n_physical_outputs.get (DataType::AUDIO);
-                                       uint32_t limit = _monitor_out->n_outputs().get (DataType::AUDIO);
-
-                                       if (mod != 0) {
-
-                                               for (uint32_t n = 0; n < limit; ++n) {
-
-                                                       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 (
-                                                                                       _("cannot connect control output %1 to %2"),
-                                                                                       n, connect_to)
-                                                                               << endmsg;
-                                                                       break;
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
+       for (RouteList::iterator x = rls->begin(); x != rls->end(); ++x) {
+               
+               if ((*x)->is_monitor()) {
+                       /* relax */
+               } else if ((*x)->is_master()) {
+                       /* relax */
+               } else {
+                       (*x)->enable_monitor_send ();
                }
        }
-
-       _state_of_the_state = StateOfTheState (_state_of_the_state & ~(CannotSave|Dirty));
-
-       /* hook us up to the engine */
-
-       BootMessage (_("Connect to engine"));
-       _engine.set_session (this);
-
-       update_latency_compensation (true);
 }
 
 void
@@ -686,35 +1016,12 @@ Session::hookup_io ()
        /* Tell all IO objects to connect themselves together */
 
        IO::enable_connecting ();
-       MIDI::Port::MakeConnections ();
 
-       /* Now reset all panners */
-
-       Delivery::reset_panners ();
-
-       /* Connect tracks to monitor/listen bus if there is one.  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.
+       /* Now tell all "floating" ports to connect to whatever
+          they should be connected to.
        */
 
-       if (_monitor_out) {
-               boost::shared_ptr<RouteList> r = routes.reader ();
-               for (RouteList::iterator x = r->begin(); x != r->end(); ++x) {
-
-                       if ((*x)->is_monitor()) {
-
-                               /* relax */
-
-                       } else if ((*x)->is_master()) {
-
-                               /* relax */
-
-                       } else {
-
-                               (*x)->listen_via_monitor ();
-                       }
-               }
-       }
+       AudioEngine::instance()->reconnect_ports ();
 
        /* Anyone who cares about input state, wake up and do something */
 
@@ -776,21 +1083,11 @@ Session::set_track_monitor_input_status (bool yn)
                boost::shared_ptr<AudioTrack> tr = boost::dynamic_pointer_cast<AudioTrack> (*i);
                if (tr && tr->record_enabled ()) {
                        //cerr << "switching to input = " << !auto_input << __FILE__ << __LINE__ << endl << endl;
-                       tr->monitor_input (yn);
+                       tr->request_input_monitoring (yn);
                }
        }
 }
 
-void
-Session::reset_input_monitor_state ()
-{
-       if (transport_rolling()) {
-               set_track_monitor_input_status (Config->get_monitoring_model() == HardwareMonitoring && !config.get_auto_input());
-       } else {
-               set_track_monitor_input_status (Config->get_monitoring_model() == HardwareMonitoring);
-       }
-}
-
 void
 Session::auto_punch_start_changed (Location* location)
 {
@@ -820,10 +1117,25 @@ Session::auto_punch_changed (Location* location)
        replace_event (SessionEvent::PunchOut, when_to_stop);
 }
 
+/** @param loc A loop location.
+ *  @param pos Filled in with the start time of the required fade-out (in session frames).
+ *  @param length Filled in with the length of the required fade-out.
+ */
+void
+Session::auto_loop_declick_range (Location* loc, framepos_t & pos, framepos_t & length)
+{
+       pos = max (loc->start(), loc->end() - 64);
+       length = loc->end() - pos;
+}
+
 void
 Session::auto_loop_changed (Location* location)
 {
        replace_event (SessionEvent::AutoLoop, location->end(), location->start());
+       framepos_t dcp;
+       framecnt_t dcl;
+       auto_loop_declick_range (location, dcp, dcl);
+       replace_event (SessionEvent::AutoLoopDeclick, dcp, dcl);
 
        if (transport_rolling() && play_loop) {
 
@@ -901,6 +1213,10 @@ Session::set_auto_loop_location (Location* location)
                loop_connections.drop_connections ();
                existing->set_auto_loop (false, this);
                remove_event (existing->end(), SessionEvent::AutoLoop);
+               framepos_t dcp;
+               framecnt_t dcl;
+               auto_loop_declick_range (existing, dcp, dcl);
+               remove_event (dcp, SessionEvent::AutoLoopDeclick);
                auto_loop_location_changed (0);
        }
 
@@ -911,7 +1227,7 @@ Session::set_auto_loop_location (Location* location)
        }
 
        if (location->end() <= location->start()) {
-               error << _("Session: you can't use a mark for auto loop") << endmsg;
+               error << _("You cannot use this location for auto-loop because it has zero or negative length") << endmsg;
                return;
        }
 
@@ -985,17 +1301,22 @@ Session::handle_locations_changed (Locations::LocationList& locations)
 void
 Session::enable_record ()
 {
+       if (_transport_speed != 0.0 && _transport_speed != 1.0) {
+               /* no recording at anything except normal speed */
+               return;
+       }
+
        while (1) {
                RecordState rs = (RecordState) g_atomic_int_get (&_record_status);
 
                if (rs == Recording) {
                        break;
                }
-
+               
                if (g_atomic_int_compare_and_exchange (&_record_status, rs, Recording)) {
 
                        _last_record_location = _transport_frame;
-                       MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
+                       _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordStrobe));
 
                        if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
                                set_track_monitor_input_status (true);
@@ -1016,7 +1337,7 @@ Session::disable_record (bool rt_context, bool force)
 
                if ((!Config->get_latched_record_enable () && !play_loop) || force) {
                        g_atomic_int_set (&_record_status, Disabled);
-                       MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
+                       _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordExit));
                } else {
                        if (rs == Recording) {
                                g_atomic_int_set (&_record_status, Enabled);
@@ -1043,6 +1364,8 @@ Session::step_back_from_record ()
                if (Config->get_monitoring_model() == HardwareMonitoring && config.get_auto_input()) {
                        set_track_monitor_input_status (false);
                }
+
+               RecordStateChanged (); /* emit signal */
        }
 }
 
@@ -1068,7 +1391,7 @@ Session::maybe_enable_record ()
                        enable_record ();
                }
        } else {
-               MIDI::Manager::instance()->mmc()->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
+               _mmc->send (MIDI::MachineControlCommand (MIDI::MachineControl::cmdRecordPause));
                RecordStateChanged (); /* EMIT SIGNAL */
        }
 
@@ -1105,7 +1428,7 @@ Session::audible_frame () const
                offset = current_block_size;
        }
 
-       if (synced_to_jack()) {
+       if (synced_to_engine()) {
                tf = _engine.transport_frame();
        } else {
                tf = _transport_frame;
@@ -1123,7 +1446,7 @@ Session::audible_frame () const
                   of audible frames, we have not moved yet.
 
                   `Start position' in this context means the time we last
-                  either started or changed transport direction.
+                  either started, located, or changed transport direction.
                */
 
                if (_transport_speed > 0.0f) {
@@ -1165,11 +1488,10 @@ Session::set_frame_rate (framecnt_t frames_per_second)
        */
 
        _base_frame_rate = frames_per_second;
+       _nominal_frame_rate = frames_per_second;
 
        sync_time_vars();
 
-       Automatable::set_automation_interval (ceil ((double) frames_per_second * (0.001 * Config->get_automation_interval())));
-
        clear_clicks ();
 
        // XXX we need some equivalent to this, somehow
@@ -1212,56 +1534,6 @@ Session::set_block_size (pframes_t nframes)
        }
 }
 
-struct RouteSorter {
-    /** @return true to run r1 before r2, otherwise false */
-    bool sort_by_rec_enabled (const boost::shared_ptr<Route>& r1, const boost::shared_ptr<Route>& r2) {
-            if (r1->record_enabled()) {
-                    if (r2->record_enabled()) {
-                            /* both rec-enabled, just use signal order */
-                            return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
-                    } else {
-                            /* r1 rec-enabled, r2 not rec-enabled, run r2 early */
-                            return false;
-                    }
-            } else {
-                    if (r2->record_enabled()) {
-                            /* r2 rec-enabled, r1 not rec-enabled, run r1 early */
-                            return true;
-                    } else {
-                            /* neither rec-enabled, use signal order */
-                            return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
-                    }
-            }
-    }
-
-    bool operator() (boost::shared_ptr<Route> r1, boost::shared_ptr<Route> r2) {
-           if (r2->feeds (r1)) {
-                   /* r1 fed by r2; run r2 early */
-                   return false;
-           } else if (r1->feeds (r2)) {
-                   /* r2 fed by r1; run r1 early */
-                   return true;
-           } else {
-                   if (r1->not_fed ()) {
-                           if (r2->not_fed ()) {
-                                   /* no ardour-based connections inbound to either route. */
-                                    return sort_by_rec_enabled (r1, r2);
-                           } else {
-                                   /* r2 has connections, r1 does not; run r1 early */
-                                   return true;
-                           }
-                   } else {
-                           if (r2->not_fed()) {
-                                   /* r1 has connections, r2 does not; run r2 early */
-                                   return false;
-                           } else {
-                                   /* both r1 and r2 have connections, but not to each other. just use signal order */
-                                   return r1->order_key(N_("signal")) < r2->order_key(N_("signal"));
-                           }
-                   }
-           }
-    }
-};
 
 static void
 trace_terminal (boost::shared_ptr<Route> r1, boost::shared_ptr<Route> rbase)
@@ -1317,10 +1589,11 @@ void
 Session::resort_routes ()
 {
        /* don't do anything here with signals emitted
-          by Routes while we are being destroyed.
+          by Routes during initial setup or while we
+          are being destroyed.
        */
 
-       if (_state_of_the_state & Deletion) {
+       if (_state_of_the_state & (InitialConnecting | Deletion)) {
                return;
        }
 
@@ -1331,8 +1604,6 @@ Session::resort_routes ()
                /* writer goes out of scope and forces update */
        }
 
-       //route_graph->dump(1);
-
 #ifndef NDEBUG
        boost::shared_ptr<RouteList> rl = routes.reader ();
        for (RouteList::iterator i = rl->begin(); i != rl->end(); ++i) {
@@ -1350,52 +1621,101 @@ Session::resort_routes ()
 #endif
 
 }
+
+/** This is called whenever we need to rebuild the graph of how we will process
+ *  routes.
+ *  @param r List of routes, in any order.
+ */
+
 void
 Session::resort_routes_using (boost::shared_ptr<RouteList> r)
 {
-       RouteList::iterator i, j;
-
-       for (i = r->begin(); i != r->end(); ++i) {
+       /* 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:
+        *
+        * 1. Collect the edges of the route graph.  Each of these edges
+        *    is a pair of routes, one of which directly feeds the other
+        *    either by a JACK connection or by an internal send.
+        *
+        * 2. Begin the process of making routes aware of which other
+        *    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 */
                (*i)->clear_fed_by ();
 
-               for (j = r->begin(); j != r->end(); ++j) {
-
-                       /* although routes can feed themselves, it will
-                          cause an endless recursive descent if we
-                          detect it. so don't bother checking for
-                          self-feeding.
-                       */
-
-                       if (*j == *i) {
-                               continue;
-                       }
+               for (RouteList::iterator j = r->begin(); j != r->end(); ++j) {
 
                        bool via_sends_only;
 
-                       if ((*j)->direct_feeds (*i, &via_sends_only)) {
+                       /* See if this *j feeds *i according to the current state of the JACK
+                          connections and internal sends.
+                       */
+                       if ((*j)->direct_feeds_according_to_reality (*i, &via_sends_only)) {
+                               /* add the edge to the graph (part #1) */
+                               edges.add (*j, *i, via_sends_only);
+                               /* tell the route (for part #2) */
                                (*i)->add_fed_by (*j, via_sends_only);
                        }
                }
        }
 
-       for (i = r->begin(); i != r->end(); ++i) {
-               trace_terminal (*i, *i);
-       }
+       /* 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.
 
-       RouteSorter cmp;
-       r->sort (cmp);
+                  Note: the process graph rechain does not require a
+                  topologically-sorted list, but hey ho.
+               */
+               if (_process_graph) {
+                       _process_graph->rechain (sorted_routes, edges);
+               }
+               
+               _current_route_graph = edges;
 
-       route_graph->rechain (r);
+               /* Complete the building of the routes' lists of what directly
+                  or indirectly feeds them.
+               */
+               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+                       trace_terminal (*i, *i);
+               }
+
+               *r = *sorted_routes;
 
 #ifndef NDEBUG
-       DEBUG_TRACE (DEBUG::Graph, "Routes resorted, order follows:\n");
-       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 signal order %2\n",
-                                                          (*i)->name(), (*i)->order_key ("signal")));
-       }
+               DEBUG_TRACE (DEBUG::Graph, "Routes resorted, order follows:\n");
+               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+                       DEBUG_TRACE (DEBUG::Graph, string_compose ("\t%1 signal order %2\n",
+                                                                  (*i)->name(), (*i)->order_key (MixerSort)));
+               }
 #endif
 
+               SuccessfulGraphSort (); /* EMIT SIGNAL */
+
+       } else {
+               /* The topological sort failed, so we have a problem.  Tell everyone
+                  and stick to the old graph; this will continue to be processed, so
+                  until the feedback is fixed, what is played back will not quite
+                  reflect what is actually connected.  Note also that we do not
+                  do trace_terminal here, as it would fail due to an endless recursion,
+                  so the solo code will think that everything is still connected
+                  as it was before.
+               */
+               
+               FeedbackDetected (); /* EMIT SIGNAL */
+       }
+
 }
 
 /** Find a route name starting with \a base, maybe followed by the
@@ -1427,7 +1747,7 @@ Session::find_route_name (string const & base, uint32_t& id, char* name, size_t
                }
 
                ++id;
-
+               
        } while (id < (UINT_MAX-1));
 
        return false;
@@ -1444,7 +1764,7 @@ Session::count_existing_track_channels (ChanCount& in, ChanCount& out)
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                 boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
-               if (tr && !tr->is_hidden()) {
+               if (tr && !tr->is_auditioner()) {
                        in  += tr->n_inputs();
                        out += tr->n_outputs();
                }
@@ -1452,24 +1772,23 @@ Session::count_existing_track_channels (ChanCount& in, ChanCount& out)
 }
 
 /** Caller must not hold process lock
- *  @param name_template string to use for the start of the name, or "" to use "Midi".
+ *  @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 (TrackMode mode, RouteGroup* route_group, uint32_t how_many, string name_template)
+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];
        uint32_t track_id = 0;
        string port;
        RouteList new_routes;
        list<boost::shared_ptr<MidiTrack> > ret;
-       uint32_t control_id;
-
-       control_id = ntracks() + nbusses();
 
-       bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("Midi");
+       bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("MIDI");
 
        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, sizeof(track_name), use_number)) {
                        error << "cannot find name for new midi track" << endmsg;
                        goto failed;
                }
@@ -1486,17 +1805,17 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m
                        track->use_new_diskstream();
 
 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
-                       boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
+                       // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
 #endif
                        {
-                               Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
-                               if (track->input()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
-                                       error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
+                               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;     
                                        goto failed;
                                }
 
-                               if (track->output()->ensure_io (ChanCount(DataType::MIDI, 1), false, this)) {
-                                       error << "cannot configure 1 in/1 out configuration for new midi track" << endmsg;
+                               if (track->output()->ensure_io (output, false, this)) {
+                                       error << "cannot configure " << output << " out configuration for new midi track" << endmsg;
                                        goto failed;
                                }
                        }
@@ -1508,7 +1827,10 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m
                        }
 
                        track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this));
-                       track->set_remote_control_id (control_id);
+
+                       if (Config->get_remote_model() == UserOrdered) {
+                               track->set_remote_control_id (next_control_id());
+                       }
 
                        new_routes.push_back (track);
                        ret.push_back (track);
@@ -1521,7 +1843,7 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m
 
                catch (AudioEngine::PortRegistrationFailure& pfe) {
 
-                       error << string_compose (_("No more JACK ports are available. You will need to stop %1 and restart JACK with ports if you need this many tracks."), PROGRAM_NAME) << endmsg;
+                       error << string_compose (_("No more JACK ports are available. You will need to stop %1 and restart JACK with more ports if you need this many tracks."), PROGRAM_NAME) << endmsg;
                        goto failed;
                }
 
@@ -1530,7 +1852,16 @@ Session::new_midi_track (TrackMode mode, RouteGroup* route_group, uint32_t how_m
 
   failed:
        if (!new_routes.empty()) {
-               add_routes (new_routes, true, true);
+               add_routes (new_routes, true, true, true);
+
+               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);
+                               
+                       }
+               }
        }
 
        return ret;
@@ -1577,7 +1908,7 @@ Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing
                return;
        }
 
-       Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock (), Glib::NOT_LOCK);
+       Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock (), Glib::Threads::NOT_LOCK);
 
        if (with_lock) {
                lm.acquire ();
@@ -1680,18 +2011,14 @@ Session::auto_connect_route (boost::shared_ptr<Route> route, ChanCount& existing
  *  @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, uint32_t how_many, string name_template
-       )
+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];
        uint32_t track_id = 0;
        string port;
        RouteList new_routes;
        list<boost::shared_ptr<AudioTrack> > ret;
-       uint32_t control_id;
-
-       control_id = ntracks() + nbusses() + 1;
 
        bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("Audio");
 
@@ -1713,10 +2040,10 @@ Session::new_audio_track (
                        track->use_new_diskstream();
 
 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
-                       boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
+                       // boost_debug_shared_ptr_mark_interesting (track.get(), "Track");
 #endif
                        {
-                               Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                               Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
 
                                if (track->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
                                        error << string_compose (
@@ -1742,8 +2069,9 @@ Session::new_audio_track (
                        track->non_realtime_input_change();
 
                        track->DiskstreamChanged.connect_same_thread (*this, boost::bind (&Session::resort_routes, this));
-                       track->set_remote_control_id (control_id);
-                       ++control_id;
+                       if (Config->get_remote_model() == UserOrdered) {
+                               track->set_remote_control_id (next_control_id());
+                       }
 
                        new_routes.push_back (track);
                        ret.push_back (track);
@@ -1765,39 +2093,12 @@ Session::new_audio_track (
 
   failed:
        if (!new_routes.empty()) {
-               add_routes (new_routes, true, true);
+               add_routes (new_routes, true, true, true);
        }
 
        return ret;
 }
 
-void
-Session::set_remote_control_ids ()
-{
-       RemoteModel m = Config->get_remote_model();
-       bool emit_signal = false;
-
-       boost::shared_ptr<RouteList> r = routes.reader ();
-
-       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (MixerOrdered == m) {
-                       int32_t order = (*i)->order_key(N_("signal"));
-                       (*i)->set_remote_control_id (order+1, false);
-                       emit_signal = true;
-               } else if (EditorOrdered == m) {
-                       int32_t order = (*i)->order_key(N_("editor"));
-                       (*i)->set_remote_control_id (order+1, false);
-                       emit_signal = true;
-               } else if (UserOrdered == m) {
-                       //do nothing ... only changes to remote id's are initiated by user
-               }
-       }
-
-       if (emit_signal) {
-               Route::RemoteControlIDChange();
-       }
-}
-
 /** Caller must not hold process lock.
  *  @param name_template string to use for the start of the name, or "" to use "Bus".
  */
@@ -1808,9 +2109,6 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
        uint32_t bus_id = 0;
        string port;
        RouteList ret;
-       uint32_t control_id;
-
-       control_id = ntracks() + nbusses() + 1;
 
        bool const use_number = (how_many != 1) || name_template.empty () || name_template == _("Bus");
        
@@ -1828,10 +2126,10 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
                        }
 
 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
-                       boost_debug_shared_ptr_mark_interesting (bus.get(), "Route");
+                       // boost_debug_shared_ptr_mark_interesting (bus.get(), "Route");
 #endif
                        {
-                               Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                               Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
 
                                if (bus->input()->ensure_io (ChanCount(DataType::AUDIO, input_channels), false, this)) {
                                        error << string_compose (_("cannot configure %1 in/%2 out configuration for new audio track"),
@@ -1852,12 +2150,15 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
                        if (route_group) {
                                route_group->add (bus);
                        }
-                       bus->set_remote_control_id (control_id);
-                       ++control_id;
+                       if (Config->get_remote_model() == UserOrdered) {
+                               bus->set_remote_control_id (next_control_id());
+                       }
 
                        bus->add_internal_return ();
 
                        ret.push_back (bus);
+                       
+                       ARDOUR::GUIIdle ();
                }
 
 
@@ -1877,7 +2178,7 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
 
   failure:
        if (!ret.empty()) {
-               add_routes (ret, true, true);
+               add_routes (ret, false, true, true); // autoconnect outputs only
        }
 
        return ret;
@@ -1885,13 +2186,13 @@ Session::new_audio_route (int input_channels, int output_channels, RouteGroup* r
 }
 
 RouteList
-Session::new_route_from_template (uint32_t how_many, const std::string& template_path)
+Session::new_route_from_template (uint32_t how_many, const std::string& template_path, const std::string& name_base)
 {
-       char name[32];
        RouteList ret;
        uint32_t control_id;
        XMLTree tree;
        uint32_t number = 0;
+       const uint32_t being_added = how_many;
 
        if (!tree.read (template_path.c_str())) {
                return ret;
@@ -1899,31 +2200,57 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
 
        XMLNode* node = tree.root();
 
-       control_id = ntracks() + nbusses() + 1;
+       IO::disable_connecting ();
+
+       control_id = next_control_id ();
 
        while (how_many) {
 
-               XMLNode node_copy (*node); // make a copy so we can change the name if we need to
+               XMLNode node_copy (*node);
 
-               std::string node_name = IO::name_from_state (*node_copy.children().front());
+               /* Remove IDs of everything so that new ones are used */
+               node_copy.remove_property_recursively (X_("id"));
 
-               /* generate a new name by adding a number to the end of the template name */
-               if (!find_route_name (node_name.c_str(), ++number, name, sizeof(name), true)) {
-                       fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
-                       /*NOTREACHED*/
-               }
+               try {
+                       char name[32];
+
+                       if (!name_base.empty()) {
 
-               /* set IO children to use the new name */
-               XMLNodeList const & children = node_copy.children ();
-               for (XMLNodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
-                       if ((*i)->name() == IO::state_node_name) {
-                               IO::set_name_in_state (**i, name);
+                               /* if we're adding more than one routes, force
+                                * all the names of the new routes to be
+                                * numbered, via the final parameter.
+                                */
+
+                               if (!find_route_name (name_base.c_str(), ++number, name, sizeof(name), (being_added > 1))) {
+                                       fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
+                                       /*NOTREACHDE*/
+                               }
+
+                       } 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)) {
+                                       fatal << _("Session: UINT_MAX routes? impossible!") << endmsg;
+                                       /*NOTREACHED*/
+                               }
                        }
-               }
 
-               Track::zero_diskstream_id_in_xml (node_copy);
+                       /* set this name in the XML description that we are about to use */
+                       Route::set_name_in_state (node_copy, name);
 
-               try {
+                       /* trim bitslots from listen sends so that new ones are used */
+                       XMLNodeList children = node_copy.children ();
+                       for (XMLNodeList::iterator i = children.begin(); i != children.end(); ++i) {
+                               if ((*i)->name() == X_("Processor")) {
+                                       XMLProperty* role = (*i)->property (X_("role"));
+                                       if (role && role->value() == X_("Listen")) {
+                                               (*i)->remove_property (X_("bitslot"));
+                                       }
+                               }
+                       }
+                       
                        boost::shared_ptr<Route> route (XMLRouteFactory (node_copy, 3000));
 
                        if (route == 0) {
@@ -1937,7 +2264,7 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
                                   loading this normally happens in a different way.
                                */
 
-                               Glib::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
+                               Glib::Threads::Mutex::Lock lm (AudioEngine::instance()->process_lock ());
 
                                IOChange change (IOChange::Type (IOChange::ConfigurationChanged | IOChange::ConnectionsChanged));
                                change.after = route->input()->n_ports();
@@ -1967,17 +2294,44 @@ Session::new_route_from_template (uint32_t how_many, const std::string& template
 
   out:
        if (!ret.empty()) {
-               add_routes (ret, true, true);
+               add_routes (ret, true, true, true);
+               IO::enable_connecting ();
        }
 
        return ret;
 }
 
 void
-Session::add_routes (RouteList& new_routes, bool auto_connect, bool save)
+Session::add_routes (RouteList& new_routes, bool input_auto_connect, bool output_auto_connect, bool save)
+{
+       try {
+               PBD::Unwinder<bool> aip (_adding_routes_in_progress, true);
+               add_routes_inner (new_routes, input_auto_connect, output_auto_connect);
+
+       } catch (...) {
+               error << _("Adding new tracks/busses failed") << endmsg;
+       }
+
+       graph_reordered ();
+
+       update_latency (true);
+       update_latency (false);
+               
+       set_dirty();
+       
+       if (save) {
+               save_state (_current_snapshot_name);
+       }
+       
+       RouteAdded (new_routes); /* EMIT SIGNAL */
+}
+
+void
+Session::add_routes_inner (RouteList& new_routes, bool input_auto_connect, bool output_auto_connect)
 {
         ChanCount existing_inputs;
         ChanCount existing_outputs;
+       uint32_t order = next_control_id();
 
         count_existing_track_channels (existing_inputs, existing_outputs);
 
@@ -1986,7 +2340,6 @@ Session::add_routes (RouteList& new_routes, bool auto_connect, bool save)
                boost::shared_ptr<RouteList> r = writer.get_copy ();
                r->insert (r->end(), new_routes.begin(), new_routes.end());
 
-
                /* if there is no control out and we're not in the middle of loading,
                   resort the graph here. if there is a control out, we will resort
                   toward the end of this method. if we are in the middle of loading,
@@ -2009,7 +2362,6 @@ Session::add_routes (RouteList& new_routes, bool auto_connect, bool save)
                r->mute_changed.connect_same_thread (*this, boost::bind (&Session::route_mute_changed, this, _1));
                r->output()->changed.connect_same_thread (*this, boost::bind (&Session::set_worst_io_latencies_x, this, _1, _2));
                r->processors_changed.connect_same_thread (*this, boost::bind (&Session::route_processors_changed, this, _1));
-               r->order_key_changed.connect_same_thread (*this, boost::bind (&Session::route_order_key_changed, this));
 
                if (r->is_master()) {
                        _master_out = r;
@@ -2032,34 +2384,45 @@ Session::add_routes (RouteList& new_routes, bool auto_connect, bool save)
                        }
                }
 
-               if (auto_connect) {
-                       auto_connect_route (r, existing_inputs, existing_outputs, true);
+
+               if (input_auto_connect || output_auto_connect) {
+                       auto_connect_route (r, existing_inputs, existing_outputs, true, input_auto_connect);
+               }
+
+               /* order keys are a GUI responsibility but we need to set up
+                  reasonable defaults because they also affect the remote control
+                  ID in most situations.
+               */
+
+               if (!r->has_order_key (EditorSort)) {
+                       if (r->is_auditioner()) {
+                               /* use an arbitrarily high value */
+                               r->set_order_key (EditorSort, UINT_MAX);
+                               r->set_order_key (MixerSort, UINT_MAX);
+                       } else {
+                               DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("while adding, set %1 to order key %2\n", r->name(), order));
+                               r->set_order_key (EditorSort, order);
+                               r->set_order_key (MixerSort, order);
+                               order++;
+                       }
                }
+
+               ARDOUR::GUIIdle ();
        }
 
        if (_monitor_out && IO::connecting_legal) {
-
+               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 */
                        } else if ((*x)->is_master()) {
-                               /* relax */
+                                       /* relax */
                        } else {
-                               (*x)->listen_via_monitor ();
+                               (*x)->enable_monitor_send ();
                        }
                }
-
-               resort_routes ();
        }
-
-       set_dirty();
-
-       if (save) {
-               save_state (_current_snapshot_name);
-       }
-
-       RouteAdded (new_routes); /* EMIT SIGNAL */
-       Route::RemoteControlIDChange (); /* EMIT SIGNAL */
 }
 
 void
@@ -2109,7 +2472,8 @@ Session::globally_add_internal_sends (boost::shared_ptr<Route> dest, Placement p
        boost::shared_ptr<RouteList> t (new RouteList);
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (include_buses || boost::dynamic_pointer_cast<Track>(*i)) {
+               /* no MIDI sends because there are no MIDI busses yet */
+               if (include_buses || boost::dynamic_pointer_cast<AudioTrack>(*i)) {
                        t->push_back (*i);
                }
        }
@@ -2120,22 +2484,29 @@ Session::globally_add_internal_sends (boost::shared_ptr<Route> dest, Placement p
 void
 Session::add_internal_sends (boost::shared_ptr<Route> dest, Placement p, boost::shared_ptr<RouteList> senders)
 {
-       if (dest->is_monitor() || dest->is_master()) {
+       for (RouteList::iterator i = senders->begin(); i != senders->end(); ++i) {
+               add_internal_send (dest, (*i)->before_processor_for_placement (p), *i);
+       }
+}
+
+void
+Session::add_internal_send (boost::shared_ptr<Route> dest, int index, boost::shared_ptr<Route> sender)
+{
+       add_internal_send (dest, sender->before_processor_for_index (index), sender);
+}
+
+void
+Session::add_internal_send (boost::shared_ptr<Route> dest, boost::shared_ptr<Processor> before, boost::shared_ptr<Route> sender)
+{
+       if (sender->is_monitor() || sender->is_master() || sender == dest || dest->is_monitor() || dest->is_master()) {
                return;
        }
 
        if (!dest->internal_return()) {
-               dest->add_internal_return();
+               dest->add_internal_return ();
        }
 
-       for (RouteList::iterator i = senders->begin(); i != senders->end(); ++i) {
-
-               if ((*i)->is_monitor() || (*i)->is_master() || (*i) == dest) {
-                       continue;
-               }
-
-               (*i)->listen_via (dest, p);
-       }
+       sender->add_aux_send (dest, before);
 
        graph_reordered ();
 }
@@ -2143,7 +2514,7 @@ Session::add_internal_sends (boost::shared_ptr<Route> dest, Placement p, boost::
 void
 Session::remove_route (boost::shared_ptr<Route> route)
 {
-       if (((route == _master_out) || (route == _monitor_out)) && !Config->get_allow_special_bus_removal()) {
+       if (route == _master_out) {
                return;
        }
 
@@ -2165,13 +2536,6 @@ Session::remove_route (boost::shared_ptr<Route> route)
                }
 
                if (route == _monitor_out) {
-
-                       /* cancel control outs for all routes */
-
-                       for (RouteList::iterator r = rs->begin(); r != rs->end(); ++r) {
-                               (*r)->drop_listen (_monitor_out);
-                       }
-
                        _monitor_out.reset ();
                }
 
@@ -2212,7 +2576,9 @@ Session::remove_route (boost::shared_ptr<Route> route)
         */
 
        resort_routes ();
-       route_graph->clear_other_chain ();
+       if (_process_graph) {
+               _process_graph->clear_other_chain ();
+       }
 
        /* get rid of it from the dead wood collection in the route list manager */
 
@@ -2224,8 +2590,6 @@ Session::remove_route (boost::shared_ptr<Route> route)
 
        route->drop_references ();
 
-       sync_order_keys (N_("session"));
-
        Route::RemoteControlIDChange(); /* EMIT SIGNAL */
 
        /* save the new state of the world */
@@ -2256,7 +2620,7 @@ Session::route_listen_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
                        /* new listen: disable all other listen */
                        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_hidden()) {
+                               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner()) {
                                        continue;
                                }
                                (*i)->set_listen (false, this);
@@ -2305,6 +2669,8 @@ Session::route_solo_isolated_changed (void* /*src*/, boost::weak_ptr<Route> wpr)
 void
 Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_ptr<Route> wpr)
 {
+       DEBUG_TRACE (DEBUG::Solo, string_compose ("route solo change, self = %1\n", self_solo_change));
+
        if (!self_solo_change) {
                // session doesn't care about changes to soloed-by-others
                return;
@@ -2312,16 +2678,12 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
 
        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 ();
-
-       if (!route) {
-               /* should not happen */
-               error << string_compose (_("programming error: %1"), X_("invalid route weak ptr passed to route_solo_changed")) << endmsg;
-               return;
-       }
+       assert (route);
 
        boost::shared_ptr<RouteList> r = routes.reader ();
        int32_t delta;
@@ -2332,42 +2694,84 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
                delta = -1;
        }
 
+       RouteGroup* rg = route->route_group ();
+       bool leave_group_alone = (rg && rg->is_active() && rg->is_solo());
+
        if (delta == 1 && Config->get_exclusive_solo()) {
-               /* new solo: disable all other solos */
+               
+               /* new solo: disable all other solos, but not the group if its solo-enabled */
+
                for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                       if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
+                       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_solo (false, this);
                }
        }
 
+       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()));
+
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                bool via_sends_only;
                bool in_signal_flow;
 
-               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_hidden()) {
+               if ((*i) == route || (*i)->solo_isolated() || (*i)->is_master() || (*i)->is_monitor() || (*i)->is_auditioner() ||
+                   (leave_group_alone && ((*i)->route_group() == rg))) {
                        continue;
                }
 
                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) {
                                if (!route->soloed_by_others_upstream()) {
                                        (*i)->mod_solo_by_others_downstream (delta);
                                }
-                               in_signal_flow = true;
+                       } else {
+                               DEBUG_TRACE (DEBUG::Solo, string_compose ("\tthere is a send-only feed from %1\n", (*i)->name()));
                        }
+                       in_signal_flow = true;
+               } 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)) {
-                       (*i)->mod_solo_by_others_upstream (delta);
+                       /* propagate solo upstream only if routing other than
+                          sends is involved, but do consider the other route
+                          (*i) to be part of the signal flow even if only
+                          sends are involved.
+                       */
+                       DEBUG_TRACE (DEBUG::Solo, string_compose ("%1 feeds %2 via sends only %3 sboD %4 sboU %5\n",
+                                                                 route->name(),
+                                                                 (*i)->name(),
+                                                                 via_sends_only,
+                                                                 route->soloed_by_others_downstream(),
+                                                                 route->soloed_by_others_upstream()));
+                       if (!via_sends_only) {
+                               if (!route->soloed_by_others_downstream()) {
+                                       DEBUG_TRACE (DEBUG::Solo, string_compose ("\tmod %1 by %2\n", (*i)->name(), delta));
+                                       (*i)->mod_solo_by_others_upstream (delta);
+                               } else {
+                                       DEBUG_TRACE (DEBUG::Solo, "\talready soloed by others downstream\n");
+                               }
+                       } else {
+                               DEBUG_TRACE (DEBUG::Solo, string_compose ("\tfeed to %1 ignored, sends-only\n", (*i)->name()));
+                       }
                        in_signal_flow = true;
+               } else {
+                       DEBUG_TRACE (DEBUG::Solo, "\tno feed to\n");
                }
 
                if (!in_signal_flow) {
@@ -2376,6 +2780,8 @@ 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);
 
        /* now notify that the mute state of the routes not involved in the signal
@@ -2383,6 +2789,7 @@ Session::route_solo_changed (bool self_solo_change, void* /*src*/, boost::weak_p
        */
 
        for (RouteList::iterator i = uninvolved.begin(); i != uninvolved.end(); ++i) {
+               DEBUG_TRACE (DEBUG::Solo, string_compose ("mute change for %1, which neither feeds or is fed by %2\n", (*i)->name(), route->name()));
                (*i)->mute_changed (this);
        }
 
@@ -2404,11 +2811,11 @@ Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
        }
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_hidden() && (*i)->self_soloed()) {
+               if (!(*i)->is_master() && !(*i)->is_monitor() && !(*i)->is_auditioner() && (*i)->self_soloed()) {
                        something_soloed = true;
                }
 
-               if (!(*i)->is_hidden() && (*i)->listening_via_monitor()) {
+               if (!(*i)->is_auditioner() && (*i)->listening_via_monitor()) {
                        if (Config->get_solo_control_is_listen_control()) {
                                listeners++;
                        } else {
@@ -2426,53 +2833,150 @@ Session::update_route_solo_state (boost::shared_ptr<RouteList> r)
                SoloActive (_non_soloed_outs_muted); /* EMIT SIGNAL */
        }
 
-       _listen_cnt = listeners;
+       _listen_cnt = listeners;
+
+       if (isolated != _solo_isolated_cnt) {
+               _solo_isolated_cnt = isolated;
+               IsolatedChanged (); /* EMIT SIGNAL */
+       }
+
+       DEBUG_TRACE (DEBUG::Solo, string_compose ("solo state updated by session, soloed? %1 listeners %2 isolated %3\n",
+                                                 something_soloed, listeners, isolated));
+}
+
+boost::shared_ptr<RouteList>
+Session::get_routes_with_internal_returns() const
+{
+       boost::shared_ptr<RouteList> r = routes.reader ();
+       boost::shared_ptr<RouteList> rl (new RouteList);
+
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+               if ((*i)->internal_return ()) {
+                       rl->push_back (*i);
+               }
+       }
+       return rl;
+}
+
+bool
+Session::io_name_is_legal (const std::string& name)
+{
+       boost::shared_ptr<RouteList> r = routes.reader ();
+
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+               if ((*i)->name() == name) {
+                       return false;
+               }
+
+               if ((*i)->has_io_processor_named (name)) {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+void
+Session::set_exclusive_input_active (boost::shared_ptr<RouteList> rl, bool onoff, bool flip_others)
+{
+       RouteList rl2;
+       vector<string> connections;
+
+       /* if we are passed only a single route and we're not told to turn
+        * others off, then just do the simple thing.
+        */
+
+       if (flip_others == false && rl->size() == 1) {
+               boost::shared_ptr<MidiTrack> mt = boost::dynamic_pointer_cast<MidiTrack> (rl->front());
+               if (mt) {
+                       mt->set_input_active (onoff);
+                       return;
+               }
+       }
+
+       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);
+
+                       if (!mt) {
+                               continue;
+                       }
+
+                       if ((*r) != (*rt)) {
+                               if (mt->input_active()) {
+                                       others_are_already_on = true;
+                               }
+                       } else {
+                               /* this one needs changing */
+                               mt->set_input_active (onoff);
+                       }
+               }
+               
+               if (flip_others) {
 
-       if (isolated != _solo_isolated_cnt) {
-               _solo_isolated_cnt = isolated;
-               IsolatedChanged (); /* EMIT SIGNAL */
+                       /* 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);
+                                       if (mt) {
+                                               mt->set_input_active (!others_are_already_on);
+                                       }
+                               }
+                       }
+               }
        }
 }
 
-boost::shared_ptr<RouteList>
-Session::get_routes_with_internal_returns() const
+void
+Session::routes_using_input_from (const string& str, RouteList& rl)
 {
-       boost::shared_ptr<RouteList> r = routes.reader ();
-       boost::shared_ptr<RouteList> rl (new RouteList);
+       boost::shared_ptr<RouteList> r = routes.reader();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if ((*i)->internal_return ()) {
-                       rl->push_back (*i);
+               if ((*i)->input()->connected_to (str)) {
+                       rl.push_back (*i);
                }
        }
-       return rl;
 }
 
-bool
-Session::io_name_is_legal (const std::string& name)
+boost::shared_ptr<Route>
+Session::route_by_name (string name)
 {
        boost::shared_ptr<RouteList> r = routes.reader ();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
                if ((*i)->name() == name) {
-                       return false;
-               }
-
-               if ((*i)->has_io_processor_named (name)) {
-                       return false;
+                       return *i;
                }
        }
 
-       return true;
+       return boost::shared_ptr<Route> ((Route*) 0);
 }
 
 boost::shared_ptr<Route>
-Session::route_by_name (string name)
+Session::route_by_id (PBD::ID id)
 {
        boost::shared_ptr<RouteList> r = routes.reader ();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if ((*i)->name() == name) {
+               if ((*i)->id() == id) {
                        return *i;
                }
        }
@@ -2480,18 +2984,19 @@ Session::route_by_name (string name)
        return boost::shared_ptr<Route> ((Route*) 0);
 }
 
-boost::shared_ptr<Route>
-Session::route_by_id (PBD::ID id)
+boost::shared_ptr<Track>
+Session::track_by_diskstream_id (PBD::ID id)
 {
        boost::shared_ptr<RouteList> r = routes.reader ();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if ((*i)->id() == id) {
-                       return *i;
+               boost::shared_ptr<Track> t = boost::dynamic_pointer_cast<Track> (*i);
+               if (t && t->using_diskstream_id (id)) {
+                       return t;
                }
        }
 
-       return boost::shared_ptr<Route> ((Route*) 0);
+       return boost::shared_ptr<Track> ();
 }
 
 boost::shared_ptr<Route>
@@ -2600,7 +3105,7 @@ Session::find_whole_file_parent (boost::shared_ptr<Region const> child) const
        RegionFactory::RegionMap::const_iterator i;
        boost::shared_ptr<Region> region;
 
-       Glib::Mutex::Lock lm (region_lock);
+       Glib::Threads::Mutex::Lock lm (region_lock);
 
        for (i = regions.begin(); i != regions.end(); ++i) {
 
@@ -2646,7 +3151,7 @@ Session::destroy_sources (list<boost::shared_ptr<Source> > srcs)
        for (list<boost::shared_ptr<Source> >::iterator s = srcs.begin(); s != srcs.end(); ) {
 
                {
-                       Glib::Mutex::Lock ls (source_lock);
+                       Glib::Threads::Mutex::Lock ls (source_lock);
                        /* remove from the main source list */
                        sources.erase ((*s)->id());
                }
@@ -2699,7 +3204,7 @@ Session::add_source (boost::shared_ptr<Source> source)
        entry.second = source;
 
        {
-               Glib::Mutex::Lock lm (source_lock);
+               Glib::Threads::Mutex::Lock lm (source_lock);
                result = sources.insert (entry);
        }
 
@@ -2707,6 +3212,14 @@ 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;
@@ -2736,14 +3249,14 @@ Session::remove_source (boost::weak_ptr<Source> src)
        }
 
        {
-               Glib::Mutex::Lock lm (source_lock);
+               Glib::Threads::Mutex::Lock lm (source_lock);
 
                if ((i = sources.find (source->id())) != sources.end()) {
                        sources.erase (i);
                }
        }
 
-       if (!_state_of_the_state & InCleanup) {
+       if (!(_state_of_the_state & InCleanup)) {
 
                /* save state so we don't end up with a session file
                   referring to non-existent sources.
@@ -2756,7 +3269,7 @@ Session::remove_source (boost::weak_ptr<Source> src)
 boost::shared_ptr<Source>
 Session::source_by_id (const PBD::ID& id)
 {
-       Glib::Mutex::Lock lm (source_lock);
+       Glib::Threads::Mutex::Lock lm (source_lock);
        SourceMap::iterator i;
        boost::shared_ptr<Source> source;
 
@@ -2770,7 +3283,7 @@ Session::source_by_id (const PBD::ID& id)
 boost::shared_ptr<Source>
 Session::source_by_path_and_channel (const string& path, uint16_t chn)
 {
-       Glib::Mutex::Lock lm (source_lock);
+       Glib::Threads::Mutex::Lock lm (source_lock);
 
        for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
                boost::shared_ptr<AudioFileSource> afs
@@ -2787,7 +3300,7 @@ uint32_t
 Session::count_sources_by_origin (const string& path)
 {
        uint32_t cnt = 0;
-       Glib::Mutex::Lock lm (source_lock);
+       Glib::Threads::Mutex::Lock lm (source_lock);
 
        for (SourceMap::iterator i = sources.begin(); i != sources.end(); ++i) {
                boost::shared_ptr<FileSource> fs
@@ -2917,7 +3430,7 @@ Session::new_source_path_from_name (DataType type, const string& name)
 
        SessionDirectory sdir(get_best_session_directory_for_new_source());
 
-       sys::path p;
+       std::string p;
        if (type == DataType::AUDIO) {
                p = sdir.sound_path();
        } else if (type == DataType::MIDI) {
@@ -2927,16 +3440,13 @@ Session::new_source_path_from_name (DataType type, const string& name)
                return "";
        }
 
-       p /= name;
-       return p.to_string();
+       return Glib::build_filename (p, name);
 }
 
 string
 Session::peak_path (string base) const
 {
-       sys::path peakfile_path(_session_dir->peak_path());
-       peakfile_path /= base + peakfile_suffix;
-       return peakfile_path.to_string();
+       return Glib::build_filename (_session_dir->peak_path(), base + peakfile_suffix);
 }
 
 /** Return a unique name based on \a base for a new internal audio source */
@@ -3000,7 +3510,7 @@ Session::new_audio_source_name (const string& base, uint32_t nchan, uint32_t cha
 
                        SessionDirectory sdir((*i).path);
 
-                       string spath = sdir.sound_path().to_string();
+                       string spath = sdir.sound_path();
 
                        /* note that we search *without* the extension so that
                           we don't end up both "Audio 1-1.wav" and "Audio 1-1.caf"
@@ -3038,7 +3548,7 @@ Session::create_audio_source_for_session (size_t n_chans, string const & n, uint
        const string path    = new_source_path_from_name(DataType::AUDIO, name);
 
        return boost::dynamic_pointer_cast<AudioFileSource> (
-               SourceFactory::createWritable (DataType::AUDIO, *this, path, string(), destructive, frame_rate()));
+               SourceFactory::createWritable (DataType::AUDIO, *this, path, destructive, frame_rate()));
 }
 
 /** Return a unique name based on \a base for a new internal MIDI source */
@@ -3063,12 +3573,11 @@ Session::new_midi_source_name (const string& base)
 
                        SessionDirectory sdir((*i).path);
 
-                       sys::path p = sdir.midi_path();
-                       p /= legalized;
+                       std::string p = Glib::build_filename (sdir.midi_path(), legalized);
 
-                       snprintf (buf, sizeof(buf), "%s-%u.mid", p.to_string().c_str(), cnt);
+                       snprintf (buf, sizeof(buf), "%s-%u.mid", p.c_str(), cnt);
 
-                       if (sys::exists (buf)) {
+                       if (Glib::file_test (buf, Glib::FILE_TEST_EXISTS)) {
                                existing++;
                        }
                }
@@ -3115,7 +3624,7 @@ Session::create_midi_source_for_session (Track* track, string const & n)
 
        return boost::dynamic_pointer_cast<SMFSource> (
                SourceFactory::createWritable (
-                       DataType::MIDI, *this, path, string(), false, frame_rate()));
+                       DataType::MIDI, *this, path, false, frame_rate()));
 }
 
 
@@ -3172,12 +3681,9 @@ Session::audition_playlist ()
 void
 Session::non_realtime_set_audition ()
 {
-       if (!pending_audition_region) {
-               auditioner->audition_current_playlist ();
-       } else {
-               auditioner->audition_region (pending_audition_region);
-               pending_audition_region.reset ();
-       }
+       assert (pending_audition_region);
+       auditioner->audition_region (pending_audition_region);
+       pending_audition_region.reset ();
        AuditionActive (true); /* EMIT SIGNAL */
 }
 
@@ -3207,7 +3713,7 @@ Session::RoutePublicOrderSorter::operator() (boost::shared_ptr<Route> a, boost::
        if (b->is_monitor()) {
                return false;
        }
-       return a->order_key(N_("signal")) < b->order_key(N_("signal"));
+       return a->order_key (MixerSort) < b->order_key (MixerSort);
 }
 
 bool
@@ -3228,7 +3734,7 @@ Session::graph_reordered ()
           from a set_state() call or creating new tracks. Ditto for deletion.
        */
 
-       if (_state_of_the_state & (InitialConnecting|Deletion)) {
+       if ((_state_of_the_state & (InitialConnecting|Deletion)) || _adding_routes_in_progress) {
                return;
        }
 
@@ -3253,9 +3759,18 @@ Session::graph_reordered ()
        }
 }
 
-framecnt_t
+/** @return Number of frames that there is disk space available to write,
+ *  if known.
+ */
+boost::optional<framecnt_t>
 Session::available_capture_duration ()
 {
+       Glib::Threads::Mutex::Lock lm (space_lock);
+
+       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()) {
@@ -3416,6 +3931,26 @@ Session::next_send_id ()
        }
 }
 
+uint32_t
+Session::next_aux_send_id ()
+{
+       /* this doesn't really loop forever. just think about it */
+
+       while (true) {
+               for (boost::dynamic_bitset<uint32_t>::size_type n = 0; n < aux_send_bitset.size(); ++n) {
+                       if (!aux_send_bitset[n]) {
+                               aux_send_bitset[n] = true;
+                               return n;
+
+                       }
+               }
+
+               /* none available, so resize and try again */
+
+               aux_send_bitset.resize (aux_send_bitset.size() + 16, false);
+       }
+}
+
 uint32_t
 Session::next_return_id ()
 {
@@ -3448,6 +3983,18 @@ Session::mark_send_id (uint32_t id)
        send_bitset[id] = true;
 }
 
+void
+Session::mark_aux_send_id (uint32_t id)
+{
+       if (id >= aux_send_bitset.size()) {
+               aux_send_bitset.resize (id+16, false);
+       }
+       if (aux_send_bitset[id]) {
+               warning << string_compose (_("aux send ID %1 appears to be in use already"), id) << endmsg;
+       }
+       aux_send_bitset[id] = true;
+}
+
 void
 Session::mark_return_id (uint32_t id)
 {
@@ -3480,6 +4027,14 @@ Session::unmark_send_id (uint32_t id)
        }
 }
 
+void
+Session::unmark_aux_send_id (uint32_t id)
+{
+       if (id < aux_send_bitset.size()) {
+               aux_send_bitset[id] = false;
+       }
+}
+
 void
 Session::unmark_return_id (uint32_t id)
 {
@@ -3496,56 +4051,6 @@ Session::unmark_insert_id (uint32_t id)
        }
 }
 
-
-/* Named Selection management */
-
-boost::shared_ptr<NamedSelection>
-Session::named_selection_by_name (string name)
-{
-       Glib::Mutex::Lock lm (named_selection_lock);
-       for (NamedSelectionList::iterator i = named_selections.begin(); i != named_selections.end(); ++i) {
-               if ((*i)->name == name) {
-                       return *i;
-               }
-       }
-       return boost::shared_ptr<NamedSelection>();
-}
-
-void
-Session::add_named_selection (boost::shared_ptr<NamedSelection> named_selection)
-{
-       {
-               Glib::Mutex::Lock lm (named_selection_lock);
-               named_selections.insert (named_selections.begin(), named_selection);
-       }
-
-       set_dirty();
-
-       NamedSelectionAdded (); /* EMIT SIGNAL */
-}
-
-void
-Session::remove_named_selection (boost::shared_ptr<NamedSelection> named_selection)
-{
-       bool removed = false;
-
-       {
-               Glib::Mutex::Lock lm (named_selection_lock);
-
-               NamedSelectionList::iterator i = find (named_selections.begin(), named_selections.end(), named_selection);
-
-               if (i != named_selections.end()) {
-                       named_selections.erase (i);
-                       set_dirty();
-                       removed = true;
-               }
-       }
-
-       if (removed) {
-                NamedSelectionRemoved (); /* EMIT SIGNAL */
-       }
-}
-
 void
 Session::reset_native_file_format ()
 {
@@ -3614,7 +4119,9 @@ Session::freeze_all (InterThreadInfo& itt)
 boost::shared_ptr<Region>
 Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
                          bool /*overwrite*/, vector<boost::shared_ptr<Source> >& srcs,
-                         InterThreadInfo& itt, bool enable_processing)
+                         InterThreadInfo& itt, 
+                         boost::shared_ptr<Processor> endpoint, bool include_endpoint,
+                         bool for_export)
 {
        boost::shared_ptr<Region> result;
        boost::shared_ptr<Playlist> playlist;
@@ -3627,7 +4134,7 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
        framepos_t to_do;
        BufferSet buffers;
        SessionDirectory sdir(get_best_session_directory_for_new_source ());
-       const string sound_dir = sdir.sound_path().to_string();
+       const string sound_dir = sdir.sound_path();
        framepos_t len = end - start;
        bool need_block_size_reset = false;
        string ext;
@@ -3651,12 +4158,6 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
                goto out;
        }
 
-       /* external redirects will be a problem */
-
-       if (track.has_external_redirects()) {
-               goto out;
-       }
-
        ext = native_header_format_extension (config.get_native_file_header_format(), DataType::AUDIO);
 
        for (uint32_t chan_n = 0; chan_n < diskstream_channels.n_audio(); ++chan_n) {
@@ -3675,7 +4176,7 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
 
                try {
                        fsource = boost::dynamic_pointer_cast<AudioFileSource> (
-                               SourceFactory::createWritable (DataType::AUDIO, *this, buf, string(), false, frame_rate()));
+                               SourceFactory::createWritable (DataType::AUDIO, *this, buf, false, frame_rate()));
                }
 
                catch (failed_constructor& err) {
@@ -3686,13 +4187,14 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
                srcs.push_back (fsource);
        }
 
-       /* tell redirects that care that we are about to use a much larger blocksize */
+       /* tell redirects that care that we are about to use a much larger
+        * blocksize. this will flush all plugins too, so that they are ready
+        * to be used for this process.
+        */
 
        need_block_size_reset = true;
        track.set_block_size (chunk_size);
 
-       /* XXX need to flush all redirects */
-
        position = start;
        to_do = len;
 
@@ -3710,7 +4212,7 @@ Session::write_one_track (AudioTrack& track, framepos_t start, framepos_t end,
 
                this_chunk = min (to_do, chunk_size);
 
-               if (track.export_stuff (buffers, start, this_chunk, enable_processing)) {
+               if (track.export_stuff (buffers, start, this_chunk, endpoint, include_endpoint, for_export)) {
                        goto out;
                }
 
@@ -3797,6 +4299,12 @@ Session::gain_automation_buffer() const
        return ProcessThread::gain_automation_buffer ();
 }
 
+gain_t*
+Session::send_gain_automation_buffer() const
+{
+       return ProcessThread::send_gain_automation_buffer ();
+}
+
 pan_t**
 Session::pan_automation_buffer() const
 {
@@ -3810,11 +4318,18 @@ Session::get_silent_buffers (ChanCount count)
 }
 
 BufferSet&
-Session::get_scratch_buffers (ChanCount count)
+Session::get_scratch_buffers (ChanCount count, bool silence)
 {
-       return ProcessThread::get_scratch_buffers (count);
+       return ProcessThread::get_scratch_buffers (count, silence);
 }
 
+BufferSet&
+Session::get_route_buffers (ChanCount count, bool silence)
+{
+       return ProcessThread::get_route_buffers (count, silence);
+}
+
+
 BufferSet&
 Session::get_mix_buffers (ChanCount count)
 {
@@ -3857,36 +4372,11 @@ Session::add_automation_list(AutomationList *al)
        automation_lists[al->id()] = al;
 }
 
-void
-Session::sync_order_keys (std::string const & base)
-{
-       if (deletion_in_progress()) {
-               return;
-       }
-
-       if (!Config->get_sync_all_route_ordering()) {
-               /* leave order keys as they are */
-               return;
-       }
-
-       boost::shared_ptr<RouteList> r = routes.reader ();
-
-       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               (*i)->sync_order_keys (base);
-       }
-
-       Route::SyncOrderKeys (base); // EMIT SIGNAL
-
-       /* this might not do anything */
-
-       set_remote_control_ids ();
-}
-
 /** @return true if there is at least one record-enabled track, otherwise false */
 bool
 Session::have_rec_enabled_track () const
 {
-       return g_atomic_int_get (&_have_rec_enabled_track) == 1;
+       return g_atomic_int_get (const_cast<gint*>(&_have_rec_enabled_track)) == 1;
 }
 
 /** Update the state of our rec-enabled tracks flag */
@@ -3936,23 +4426,25 @@ Session::solo_control_mode_changed ()
        }
 }
 
-/** Called when anything about any of our route groups changes (membership, state etc.) */
+/** Called when a property of one of our route groups changes */
 void
-Session::route_group_changed ()
+Session::route_group_property_changed (RouteGroup* rg)
 {
-       RouteGroupChanged (); /* EMIT SIGNAL */
+       RouteGroupPropertyChanged (rg); /* EMIT SIGNAL */
 }
 
-vector<SyncSource>
-Session::get_available_sync_options () const
+/** Called when a route is added to one of our route groups */
+void
+Session::route_added_to_route_group (RouteGroup* rg, boost::weak_ptr<Route> r)
 {
-       vector<SyncSource> ret;
-
-       ret.push_back (JACK);
-       ret.push_back (MTC);
-       ret.push_back (MIDIClock);
+       RouteAddedToRouteGroup (rg, r);
+}
 
-       return ret;
+/** Called when a route is removed from one of our route groups */
+void
+Session::route_removed_from_route_group (RouteGroup* rg, boost::weak_ptr<Route> r)
+{
+       RouteRemovedFromRouteGroup (rg, r);
 }
 
 boost::shared_ptr<RouteList>
@@ -4019,13 +4511,6 @@ Session::add_session_range_location (framepos_t start, framepos_t end)
        _locations->add (_session_range_location);
 }
 
-/** Called when one of our routes' order keys has changed */
-void
-Session::route_order_key_changed ()
-{
-       RouteOrderKeyChanged (); /* EMIT SIGNAL */
-}
-
 void
 Session::step_edit_status_change (bool yn)
 {
@@ -4066,7 +4551,7 @@ Session::start_time_changed (framepos_t old)
 
        Location* l = _locations->auto_loop_location ();
 
-       if (l->start() == old) {
+       if (l && l->start() == old) {
                l->set_start (s->start(), true);
        }
 }
@@ -4085,70 +4570,66 @@ Session::end_time_changed (framepos_t old)
 
        Location* l = _locations->auto_loop_location ();
 
-       if (l->end() == old) {
+       if (l && l->end() == old) {
                l->set_end (s->end(), true);
        }
 }
 
-string
+std::vector<std::string>
 Session::source_search_path (DataType type) const
 {
-       string search_path;
+       Searchpath sp;
 
        if (session_dirs.size() == 1) {
                switch (type) {
                case DataType::AUDIO:
-                       search_path = _session_dir->sound_path().to_string();
+                       sp.push_back (_session_dir->sound_path());
                        break;
                case DataType::MIDI:
-                       search_path = _session_dir->midi_path().to_string();
+                       sp.push_back (_session_dir->midi_path());
                        break;
                }
        } else {
                for (vector<space_and_path>::const_iterator i = session_dirs.begin(); i != session_dirs.end(); ++i) {
                        SessionDirectory sdir (i->path);
-                       if (!search_path.empty()) {
-                               search_path += ':';
-                       }
                        switch (type) {
                        case DataType::AUDIO:
-                               search_path += sdir.sound_path().to_string();
+                               sp.push_back (sdir.sound_path());
                                break;
                        case DataType::MIDI:
-                               search_path += sdir.midi_path().to_string();
+                               sp.push_back (sdir.midi_path());
                                break;
                        }
                }
        }
 
-       /* now add user-specified locations
-        */
+       if (type == DataType::AUDIO) {
+               const string sound_path_2X = _session_dir->sound_path_2X();
+               if (Glib::file_test (sound_path_2X, Glib::FILE_TEST_EXISTS|Glib::FILE_TEST_IS_DIR)) {
+                       if (find (sp.begin(), sp.end(), sound_path_2X) == sp.end()) {
+                               sp.push_back (sound_path_2X);
+                       }
+               }
+       }
 
-       vector<string> dirs;
+       // now check the explicit (possibly user-specified) search path
 
        switch (type) {
        case DataType::AUDIO:
-               split (config.get_audio_search_path (), dirs, ':');
+               sp += Searchpath(config.get_audio_search_path ());
                break;
        case DataType::MIDI:
-               split (config.get_midi_search_path (), dirs, ':');
+               sp += Searchpath(config.get_midi_search_path ());
                break;
        }
 
-       for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
-               search_path += ':';
-               search_path += *i;
-
-       }
-
-       return search_path;
+       return sp;
 }
 
 void
 Session::ensure_search_path_includes (const string& path, DataType type)
 {
-       string search_path;
-       vector<string> dirs;
+       Searchpath sp;
 
        if (path == ".") {
                return;
@@ -4156,33 +4637,33 @@ Session::ensure_search_path_includes (const string& path, DataType type)
 
        switch (type) {
        case DataType::AUDIO:
-               search_path = config.get_audio_search_path ();
+               sp += Searchpath(config.get_audio_search_path ());
                break;
        case DataType::MIDI:
-               search_path = config.get_midi_search_path ();
+               sp += Searchpath (config.get_midi_search_path ());
                break;
        }
 
-       split (search_path, dirs, ':');
+       for (vector<std::string>::iterator i = sp.begin(); i != sp.end(); ++i) {
+               /* No need to add this new directory if it has the same inode as
+                  an existing one; checking inode rather than name prevents duplicated
+                  directories when we are using symlinks.
 
-       for (vector<string>::iterator i = dirs.begin(); i != dirs.end(); ++i) {
-               if (*i == path) {
+                  On Windows, I think we could just do if (*i == path) here.
+               */
+               if (PBD::equivalent_paths (*i, path)) {
                        return;
                }
        }
 
-       if (!search_path.empty()) {
-               search_path += ':';
-       }
-
-       search_path += path;
+       sp += path;
 
        switch (type) {
        case DataType::AUDIO:
-               config.set_audio_search_path (search_path);
+               config.set_audio_search_path (sp.to_string());
                break;
        case DataType::MIDI:
-               config.set_midi_search_path (search_path);
+               config.set_midi_search_path (sp.to_string());
                break;
        }
 }
@@ -4215,7 +4696,7 @@ Session::update_latency (bool playback)
 {
        DEBUG_TRACE (DEBUG::Latency, string_compose ("JACK latency callback: %1\n", (playback ? "PLAYBACK" : "CAPTURE")));
 
-       if (_state_of_the_state & (InitialConnecting|Deletion)) {
+       if ((_state_of_the_state & (InitialConnecting|Deletion)) || _adding_routes_in_progress) {
                return;
        }
 
@@ -4224,6 +4705,8 @@ Session::update_latency (bool playback)
 
        if (playback) {
                /* reverse the list so that we work backwards from the last route to run to the first */
+                RouteList* rl = routes.reader().get();
+                r.reset (new RouteList (*rl));
                reverse (r->begin(), r->end());
        }
 
@@ -4267,14 +4750,15 @@ Session::post_playback_latency ()
        set_worst_playback_latency ();
 
        boost::shared_ptr<RouteList> r = routes.reader ();
+
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (!(*i)->is_hidden() && ((*i)->active())) {
+               if (!(*i)->is_auditioner() && ((*i)->active())) {
                        _worst_track_latency = max (_worst_track_latency, (*i)->update_signal_latency ());
                }
+       }
 
-               for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-                       (*i)->set_latency_compensation (_worst_track_latency);
-               }
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+               (*i)->set_latency_compensation (_worst_track_latency);
        }
 }
 
@@ -4295,6 +4779,18 @@ Session::post_capture_latency ()
        }
 }
 
+void
+Session::initialize_latencies ()
+{
+        {
+                Glib::Threads::Mutex::Lock lm (_engine.process_lock());
+                update_latency (false);
+                update_latency (true);
+        }
+
+        set_worst_io_latencies ();
+}
+
 void
 Session::set_worst_io_latencies ()
 {
@@ -4362,7 +4858,7 @@ Session::update_latency_compensation (bool force_whole_graph)
        boost::shared_ptr<RouteList> r = routes.reader ();
 
        for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
-               if (!(*i)->is_hidden() && ((*i)->active())) {
+               if (!(*i)->is_auditioner() && ((*i)->active())) {
                        framecnt_t tl;
                        if ((*i)->signal_latency () != (tl = (*i)->update_signal_latency ())) {
                                some_track_latency_changed = true;
@@ -4374,15 +4870,136 @@ Session::update_latency_compensation (bool force_whole_graph)
        DEBUG_TRACE (DEBUG::Latency, string_compose ("worst signal processing latency: %1 (changed ? %2)\n", _worst_track_latency,
                                                     (some_track_latency_changed ? "yes" : "no")));
 
-       if (force_whole_graph || some_track_latency_changed) {
-               /* trigger a full recompute of latency numbers for the graph.
-                  everything else that we need to do will be done in the latency
-                  callback.
-               */
-               _engine.update_total_latencies ();
-               return; // everything else will be done in the latency callback
+       DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n");
+       
+       if (some_track_latency_changed || force_whole_graph)  {
+               _engine.update_latencies ();
+       }
+
+
+       for (RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+               boost::shared_ptr<Track> tr = boost::dynamic_pointer_cast<Track> (*i);
+               if (!tr) {
+                       continue;
+               }
+               tr->set_capture_offset ();
+       }
+}
+
+char
+Session::session_name_is_legal (const string& path)
+{
+       char illegal_chars[] = { '/', '\\', ':', ';', '\0' };
+
+       for (int i = 0; illegal_chars[i]; ++i) {
+               if (path.find (illegal_chars[i]) != string::npos) {
+                       return illegal_chars[i];
+               }
+       }
+
+       return 0;
+}
+
+uint32_t 
+Session::next_control_id () const
+{
+       int subtract = 0;
+
+       /* the monitor bus remote ID is in a different
+        * "namespace" than regular routes. its existence doesn't
+        * affect normal (low) numbered routes.
+        */
+
+       if (_monitor_out) {
+               subtract++;
+       }
+
+       return nroutes() - subtract;
+}
+
+void
+Session::notify_remote_id_change ()
+{
+       if (deletion_in_progress()) {
+               return;
+       }
+
+       switch (Config->get_remote_model()) {
+       case MixerSort:
+       case EditorSort:
+               Route::RemoteControlIDChange (); /* EMIT SIGNAL */
+               break;
+       default:
+               break;
+       }
+}
+
+void
+Session::sync_order_keys (RouteSortOrderKey sort_key_changed)
+{
+       if (deletion_in_progress()) {
+               return;
        }
 
-       DEBUG_TRACE(DEBUG::Latency, "---------------------------- DONE update latency compensation\n\n")
+       /* tell everyone that something has happened to the sort keys
+          and let them sync up with the change(s)
+          this will give objects that manage the sort order keys the
+          opportunity to keep them in sync if they wish to.
+       */
+
+       DEBUG_TRACE (DEBUG::OrderKeys, string_compose ("Sync Order Keys, based on %1\n", enum_2_string (sort_key_changed)));
+
+       Route::SyncOrderKeys (sort_key_changed); /* EMIT SIGNAL */
+
+       DEBUG_TRACE (DEBUG::OrderKeys, "\tsync done\n");
+}
+
+bool
+Session::operation_in_progress (GQuark op) const
+{
+       return (find (_current_trans_quarks.begin(), _current_trans_quarks.end(), op) != _current_trans_quarks.end());
+}
+
+boost::shared_ptr<Port>
+Session::ltc_input_port () const
+{
+       return _ltc_input->nth (0);
+}
+
+boost::shared_ptr<Port>
+Session::ltc_output_port () const
+{
+       return _ltc_output->nth (0);
+}
+
+void
+Session::reconnect_ltc_input ()
+{
+       if (_ltc_input) {
+
+               string src = Config->get_ltc_source_port();
+
+               _ltc_input->disconnect (this);
+
+               if (src != _("None") && !src.empty())  {
+                       _ltc_input->nth (0)->connect (src);
+               }
+       }
 }
 
+void
+Session::reconnect_ltc_output ()
+{
+       if (_ltc_output) {
+
+#if 0
+               string src = Config->get_ltc_sink_port();
+
+               _ltc_output->disconnect (this);
+
+               if (src != _("None") && !src.empty())  {
+                       _ltc_output->nth (0)->connect (src);
+               }
+#endif
+       }
+}