Index: gtk2_ardour/mixer_strip.cc
===================================================================
--- gtk2_ardour/mixer_strip.cc	(revision 1560)
+++ gtk2_ardour/mixer_strip.cc	(working copy)
@@ -36,6 +36,7 @@
 #include <ardour/session.h>
 #include <ardour/audioengine.h>
 #include <ardour/route.h>
+#include <ardour/session_route.h>
 #include <ardour/audio_track.h>
 #include <ardour/audio_diskstream.h>
 #include <ardour/panner.h>
@@ -511,6 +512,7 @@
 		citems.push_back (SeparatorElem());
 		
 		_session.foreach_connection (this, &MixerStrip::add_connection_to_output_menu);
+		_session.foreach_route (this, &MixerStrip::add_route_to_output_menu);
 
 		output_menu.popup (1, ev->time);
 		break;
@@ -573,6 +575,7 @@
 		citems.push_back (SeparatorElem());
 		
 		_session.foreach_connection (this, &MixerStrip::add_connection_to_input_menu);
+		_session.foreach_route (this, &MixerStrip::add_route_to_input_menu);
 
 		input_menu.popup (1, ev->time);
 		break;
@@ -710,9 +713,14 @@
 MixerStrip::update_input_display ()
 {
 	ARDOUR::Connection *c;
+	std::string r;
 
 	if ((c = _route->input_connection()) != 0) {
+		/* connection input */
 		input_label.set_text (c->name());
+	} else if ((r = input_route ()) != "") {
+		/* route input */
+		input_label.set_text (r);
 	} else {
 		switch (_width) {
 		case Wide:
@@ -730,9 +738,14 @@
 MixerStrip::update_output_display ()
 {
 	ARDOUR::Connection *c;
+	std::string r;
 
 	if ((c = _route->output_connection()) != 0) {
+		/* connection output */
 		output_label.set_text (c->name());
+	} else if ((r = output_route ()) != "") {
+		/* route output */
+		output_label.set_text (r);
 	} else {
 		switch (_width) {
 		case Wide:
@@ -1219,3 +1232,135 @@
 		gpm.setup_meters ();
 }
 
+
+void
+MixerStrip::add_route_to_output_menu (Route& r)
+{
+        using namespace Menu_Helpers;
+
+	/* we can use this route as an output if its number of inputs is the
+	   same as our number of outputs */
+
+	if (r.n_inputs() == _route->n_outputs()) {
+
+		MenuList& citems = output_menu.items ();
+		citems.push_back (CheckMenuElem (r.name(), bind (mem_fun(*this, &MixerStrip::route_output_chosen), &r)));
+
+		if (output_route () == r.name()) {
+			/* tick this item if it's active */
+			ignore_toggle = true;
+			dynamic_cast<CheckMenuItem *> (&citems.back())->set_active (true);
+			ignore_toggle = false;
+		}
+	}
+}
+
+
+
+void
+MixerStrip::add_route_to_input_menu (Route& r)
+{
+        using namespace Menu_Helpers;
+
+	/* we can use this route as an input if its number of outputs is the
+	   same as our number of inputs */
+
+	if (r.n_outputs() == _route->n_inputs()) {
+
+		MenuList& citems = input_menu.items ();
+		citems.push_back (CheckMenuElem (r.name(), bind (mem_fun(*this, &MixerStrip::route_input_chosen), &r)));
+
+		if (input_route () == r.name()) {
+			/* tick this item if it's active */
+			ignore_toggle = true;
+			dynamic_cast<CheckMenuItem *> (&citems.back())->set_active (true);
+			ignore_toggle = false;
+		}
+	}
+}
+
+
+
+void
+MixerStrip::route_output_chosen (ARDOUR::Route* r)
+{
+	_route->disconnect_outputs (this);
+	
+	for (uint32_t i = 0; i < _route->n_outputs(); i++) {
+		_route->connect_output (_route->output(i), r->input(i)->name(), this);
+	}
+}
+
+
+void
+MixerStrip::route_input_chosen (ARDOUR::Route* r)
+{
+	_route->disconnect_inputs (this);
+	
+	for (uint32_t i = 0; i < _route->n_inputs(); i++) {
+		_route->connect_input (_route->input(i), r->output(i)->name(), this);
+	}
+}
+
+
+std::string
+MixerStrip::output_route ()
+{
+	boost::shared_ptr<Session::RouteList> r = _session.get_routes ();
+
+	/* run through all the session's routes looking for one that
+	   our route's output might be connected to */
+	for (Session::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+		
+		if ( (*i)->n_inputs() == _route->n_outputs()) {
+
+			/* this route has the right number of inputs */
+
+			uint32_t j;
+			for (j = 0; j < (*i)->n_outputs(); ++j) {
+				if (!_route->output(j)->connected_to((*i)->input(j)->name())) {
+					/* this connection is not made; jump out */
+					break;
+				}
+			}
+
+			if (j == (*i)->n_outputs()) {
+				return (*i)->name ();
+			}
+		}
+	}
+
+	return "";
+}
+
+
+
+std::string
+MixerStrip::input_route ()
+{
+	boost::shared_ptr<Session::RouteList> r = _session.get_routes ();
+
+	/* run through all the session's routes looking for one that
+	   our route's input might be connected to */
+	for (Session::RouteList::iterator i = r->begin(); i != r->end(); ++i) {
+		
+		if ( (*i)->n_outputs() == _route->n_inputs()) {
+
+			/* this route has the right number of outputs */
+
+			uint32_t j;
+			for (j = 0; j < (*i)->n_inputs(); ++j) {
+				if (!_route->input(j)->connected_to((*i)->output(j)->name())) {
+					/* this connection is not made; jump out */
+					break;
+				}
+			}
+
+			if (j == (*i)->n_inputs()) {
+				return (*i)->name ();
+			}
+		}
+	}
+
+	return "";
+}
Index: gtk2_ardour/mixer_strip.h
===================================================================
--- gtk2_ardour/mixer_strip.h	(revision 1560)
+++ gtk2_ardour/mixer_strip.h	(working copy)
@@ -165,15 +165,23 @@
 	gint input_press (GdkEventButton *);
 	gint output_press (GdkEventButton *);
 
-	Gtk::Menu  input_menu;
+	Gtk::Menu input_menu;
 	void add_connection_to_input_menu (ARDOUR::Connection *);
+	void add_route_to_input_menu (ARDOUR::Route &);
 
 	Gtk::Menu output_menu;
 	void add_connection_to_output_menu (ARDOUR::Connection *);
+	void add_route_to_output_menu (ARDOUR::Route &);
 	
 	void connection_input_chosen (ARDOUR::Connection *);
 	void connection_output_chosen (ARDOUR::Connection *);
 
+	void route_input_chosen (ARDOUR::Route *);
+	void route_output_chosen (ARDOUR::Route *);
+
+	std::string input_route ();
+	std::string output_route ();
+
 	void edit_input_configuration ();
 	void edit_output_configuration ();
 
Index: libs/ardour/route.cc
===================================================================
--- libs/ardour/route.cc	(revision 1560)
+++ libs/ardour/route.cc	(working copy)
@@ -41,6 +41,7 @@
 #include <ardour/panner.h>
 #include <ardour/dB.h>
 #include <ardour/mix.h>
+#include <ardour/connection.h>
 
 #include "i18n.h"
 
Index: libs/ardour/ardour/audioengine.h
===================================================================
--- libs/ardour/ardour/audioengine.h	(revision 1560)
+++ libs/ardour/ardour/audioengine.h	(working copy)
@@ -222,7 +222,9 @@
 	typedef std::pair<std::string,std::string> PortConnection;
 	typedef std::list<PortConnection> PortConnections;
 
-	PortConnections port_connections;
+	PortConnections port_connections; ///< connections that we've made between JACK ports;
+	///< used for re-establishing connections in reconnect_to_jack ()
+  
 	void   remove_connections_for (Port*);
 
 	std::string get_nth_physical (uint32_t which, int flags);
Index: libs/ardour/ardour/route.h
===================================================================
--- libs/ardour/ardour/route.h	(revision 1560)
+++ libs/ardour/ardour/route.h	(working copy)
@@ -47,6 +47,8 @@
 class Insert;
 class Send;
 class RouteGroup;
+class InputConnection;
+class OutputConnection;
 
 enum mute_type {
     PRE_FADER =    0x1,
Index: libs/ardour/ardour/port.h
===================================================================
--- libs/ardour/ardour/port.h	(revision 1560)
+++ libs/ardour/ardour/port.h	(working copy)
@@ -29,6 +29,14 @@
 
 class AudioEngine;
 
+/// JACK Port
+
+/**
+ *  This class is basically a description of a JACK port, with
+ *  some wrappers around JACK functions.  It is identified
+ *  by a jack_port_t*.  Port objects can only be instantiated
+ *  and connections set up by the AudioEngine.
+ */
 class Port : public sigc::trackable {
    public:
 	virtual ~Port() { 
@@ -37,8 +45,10 @@
 
 	Sample *get_buffer (nframes_t nframes) {
 		if (_flags & JackPortIsOutput) {
+			/* its an output so we can use our cached value */
 			return _buffer;
 		} else {
+			/* its an input so we must ask JACK */
 			return (Sample *) jack_port_get_buffer (_port, nframes);
 		}
 	}
@@ -52,20 +62,34 @@
 		_silent = false;
 	}
 
+	/**
+	 *  \return JACK's name for this port.
+	 */
 	std::string name() { 
 		return _name;
 	}
 
+	/**
+	 *  \return JACK's short name for this port.
+	 */
 	std::string short_name() { 
 		return jack_port_short_name (_port);
 	}
-	
+
+	/**
+	 *  Set the name that JACK uses for this port.
+	 *  \param str New name.
+	 */
 	int set_name (std::string str);
 
 	JackPortFlags flags() const {
 		return _flags;
 	}
 
+	/**
+	 *  \param JACK client.
+	 *  \return true if this port belongs to `client'
+	 */
 	bool is_mine (jack_client_t *client) { 
 		return jack_port_is_mine (client, _port);
 	}
@@ -77,11 +101,20 @@
 	int connected () const {
 		return jack_port_connected (_port);
 	}
-	
+
+	/**
+	 *  \param portname Port name.
+	 *  \return true if this port is connected to `portname'
+	 */
 	bool connected_to (const std::string& portname) const {
 		return jack_port_connected_to (_port, portname.c_str());
 	}
 
+	/**
+	 *  \return NULL-terminated array of port names that this
+	 *  port is connected to, or 0.  The caller should free() the
+	 *  returned pointer.
+	 */
 	const char ** get_connections () const {
 		return jack_port_get_connections (_port);
 	}
Index: libs/ardour/audioengine.cc
===================================================================
--- libs/ardour/audioengine.cc	(revision 1560)
+++ libs/ardour/audioengine.cc	(working copy)
@@ -576,6 +576,14 @@
 	}
 }
 
+
+/**
+ *    Basic call to connect two JACK ports together.
+ *
+ *    \param source name of source JACK port.
+ *    \param destination name of destination JACK port.
+ */
+
 int 
 AudioEngine::connect (const string& source, const string& destination)
 {
@@ -587,14 +595,16 @@
 			return -1;
 		}
 	}
-	
-	string s = make_port_name_non_relative (source);
-	string d = make_port_name_non_relative (destination);
 
+	/* ensure that the port names include client names */
+	const string s = make_port_name_non_relative (source);
+	const string d = make_port_name_non_relative (destination);
+
 	int ret = jack_connect (_jack, s.c_str(), d.c_str());
 
 	if (ret == 0) {
-		pair<string,string> c (s, d);
+		/* connection ok; make a note of it */
+		const pair<string,string> c (s, d);
 		port_connections.push_back (c);
 	} else if (ret == EEXIST) {
 		error << string_compose(_("AudioEngine: connection already exists: %1 (%2) to %3 (%4)"), 
@@ -609,6 +619,13 @@
 	return ret;
 }
 
+/**
+ *    Basic call to disconnect two previously-connected JACK ports.
+ *
+ *    \param source name of source JACK port.
+ *    \param destination name of destination JACK port.
+ */
+
 int 
 AudioEngine::disconnect (const string& source, const string& destination)
 {
@@ -621,15 +638,17 @@
 		}
 	}
 	
-	string s = make_port_name_non_relative (source);
-	string d = make_port_name_non_relative (destination);
+	/* ensure that the port names include client names */
+	const string s = make_port_name_non_relative (source);
+	const string d = make_port_name_non_relative (destination);
 
 	int ret = jack_disconnect (_jack, s.c_str(), d.c_str());
 
 	if (ret == 0) {
-		pair<string,string> c (s, d);
+		/* disconnection ok; make a note of it */
+		const pair<string,string> c (s, d);
 		PortConnections::iterator i;
-		
+
 		if ((i = find (port_connections.begin(), port_connections.end(), c)) != port_connections.end()) {
 			port_connections.erase (i);
 		}
@@ -993,6 +1012,13 @@
 	port_connections.clear ();
 }
 
+/**
+ *    Remove any connections that we have made a note of in port_connections
+ *    for a given port.
+ *
+ *    \param port Port.
+ */
+
 void
 AudioEngine::remove_connections_for (Port* port)
 {
