Index: gtk2_ardour/panner_ui.h
===================================================================
--- gtk2_ardour/panner_ui.h	(revision 1765)
+++ gtk2_ardour/panner_ui.h	(working copy)
@@ -68,9 +68,11 @@
 	void effective_pan_display ();
 
 	void set_meter_strip_name (string name);
+	PBD::Controllable* get_controllable();
 
   private:
 	friend class MixerStrip;
+
 	boost::shared_ptr<ARDOUR::IO> _io;
 	ARDOUR::Session& _session;
 
Index: gtk2_ardour/panner_ui.cc
===================================================================
--- gtk2_ardour/panner_ui.cc	(revision 1765)
+++ gtk2_ardour/panner_ui.cc	(working copy)
@@ -152,6 +152,12 @@
 	pan_automation_state_changed ();
 }
 
+PBD::Controllable* 
+PannerUI::get_controllable() 
+{ 
+	return pan_bars[0]->get_controllable();
+}
+
 bool
 PannerUI::panning_link_button_press (GdkEventButton* ev)
 {
Index: gtk2_ardour/mixer_ui.h
===================================================================
--- gtk2_ardour/mixer_ui.h	(revision 1765)
+++ gtk2_ardour/mixer_ui.h	(working copy)
@@ -75,6 +75,8 @@
 	void hide_strip (MixerStrip *);
 
 	void ensure_float (Gtk::Window&);
+	void toggle_auto_rebinding ();
+	void set_auto_rebinding(bool);
 
 	RouteRedirectSelection& selection() { return _selection; }
 	
@@ -121,6 +123,9 @@
 	void unselect_all_audiobus_strips ();
 	void select_all_audiobus_strips ();
 
+	void auto_rebind_midi_controls ();
+	bool auto_rebinding;
+
 	void strip_select_op (bool audiotrack, bool select);
 	void select_strip_op (MixerStrip*, bool select);
 
Index: gtk2_ardour/ardour.menus
===================================================================
--- gtk2_ardour/ardour.menus	(revision 1765)
+++ gtk2_ardour/ardour.menus	(working copy)
@@ -295,6 +295,8 @@
                    <menuitem action='RemoteUserDefined'/>
                    <menuitem action='RemoteMixerDefined'/>
                    <menuitem action='RemoteEditorDefined'/>
+    	           <separator/>
+                   <menuitem action='AutoRebinding'/>
                </menu>
                    <menu action='Monitoring'>
                    <menuitem action='UseHardwareMonitoring'/>
Index: gtk2_ardour/ardour_ui_ed.cc
===================================================================
--- gtk2_ardour/ardour_ui_ed.cc	(revision 1765)
+++ gtk2_ardour/ardour_ui_ed.cc	(working copy)
@@ -35,6 +35,7 @@
 #include "audio_clock.h"
 #include "editor.h"
 #include "actions.h"
+#include "mixer_ui.h"
 
 #include <ardour/session.h>
 #include <ardour/profile.h>
@@ -487,6 +488,10 @@
 	act = ActionManager::register_radio_action (option_actions, remote_group, X_("RemoteEditorDefined"), _("Remote ID follows order of Editor"), hide_return (bind (mem_fun (*this, &ARDOUR_UI::set_remote_model), EditorOrdered)));
 	ActionManager::session_sensitive_actions.push_back (act);
 
+	act = ActionManager::register_toggle_action (option_actions, X_("AutoRebinding"), _("Auto Rebind Controls"), mem_fun (*(this->mixer), &Mixer_UI::toggle_auto_rebinding));
+	ActionManager::session_sensitive_actions.push_back (act);
+
+
 	ActionManager::add_action_group (shuttle_actions);
 	ActionManager::add_action_group (option_actions);
 	ActionManager::add_action_group (jack_actions);
Index: gtk2_ardour/mixer_ui.cc
===================================================================
--- gtk2_ardour/mixer_ui.cc	(revision 1765)
+++ gtk2_ardour/mixer_ui.cc	(working copy)
@@ -219,6 +219,8 @@
 	signal_configure_event().connect (mem_fun (*ARDOUR_UI::instance(), &ARDOUR_UI::configure_handler));
 
 	_selection.RoutesChanged.connect (mem_fun(*this, &Mixer_UI::follow_strip_selection));
+
+	auto_rebinding = FALSE;
 }
 
 Mixer_UI::~Mixer_UI ()
@@ -634,8 +636,90 @@
 			}
 		}
 	}
+
+	// Rebind all of the midi controls automatically
+	
+	if (auto_rebinding)
+		auto_rebind_midi_controls ();
+
 }
 
+void
+Mixer_UI::set_auto_rebinding( bool val )
+{
+	if( val == TRUE )
+	{
+		auto_rebinding = TRUE;
+		Session::AutoBindingOff();
+	}
+	else
+	{
+		auto_rebinding = FALSE;
+		Session::AutoBindingOn();
+	}
+}
+
+void 
+Mixer_UI::toggle_auto_rebinding() 
+{
+	if (auto_rebinding)
+	{
+		set_auto_rebinding( FALSE );
+	}
+	
+	else
+	{
+		set_auto_rebinding( TRUE );
+	}
+
+	auto_rebind_midi_controls();
+}
+
+void 
+Mixer_UI::auto_rebind_midi_controls () 
+{
+	TreeModel::Children rows = track_model->children();
+	TreeModel::Children::iterator i;
+	int pos;
+
+	// Create bindings for all visible strips and remove those that are not visible
+	pos = 0;
+	for (i = rows.begin(); i != rows.end(); ++i) {
+		MixerStrip* strip = (*i)[track_columns.strip];
+    
+		if ( (*i)[track_columns.visible] == true ) {  // add bindings for
+			// make the actual binding
+			//cout<<"Auto Binding:  Visible Strip Found: "<<strip->name()<<endl;
+
+			PBD::Controllable::CreateBinding ( strip->solo_button->get_controllable(), pos, 0);
+			PBD::Controllable::CreateBinding ( strip->mute_button->get_controllable(), pos, 1);
+
+			if( strip->is_audio_track() ) {
+				PBD::Controllable::CreateBinding ( strip->rec_enable_button->get_controllable(), pos, 2);
+			}
+
+			PBD::Controllable::CreateBinding ( &(strip->gpm.get_controllable()), pos, 3);
+			PBD::Controllable::CreateBinding ( strip->panners.get_controllable(), pos, 4);
+
+			pos++;
+		}
+		else {  // Remove any existing binding
+			PBD::Controllable::DeleteBinding ( strip->solo_button->get_controllable() );
+			PBD::Controllable::DeleteBinding ( strip->mute_button->get_controllable() );
+
+			if( strip->is_audio_track() ) {
+				PBD::Controllable::DeleteBinding ( strip->rec_enable_button->get_controllable() );
+			}
+
+			PBD::Controllable::DeleteBinding ( &(strip->gpm.get_controllable()) );
+			PBD::Controllable::DeleteBinding ( strip->panners.get_controllable() ); // This only takes the first panner if there are multiples...
+		}
+
+	} // for
+  
+}
+
+
 struct SignalOrderRouteSorter {
     bool operator() (boost::shared_ptr<Route> a, boost::shared_ptr<Route> b) {
 	    /* use of ">" forces the correct sort order */
@@ -991,6 +1075,7 @@
 	if (name != group->name()) {
 		group->set_name (name);
 	}
+
 }
 
 void
Index: gtk2_ardour/gain_meter.h
===================================================================
--- gtk2_ardour/gain_meter.h	(revision 1765)
+++ gtk2_ardour/gain_meter.h	(working copy)
@@ -73,6 +73,7 @@
 
 	void set_meter_strip_name (const char * name);
 	void set_fader_name (const char * name);
+	PBD::Controllable& get_controllable() { return _io->gain_control(); }
 
   private:
 
Index: libs/gtkmm2ext/gtkmm2ext/bindable_button.h
===================================================================
--- libs/gtkmm2ext/gtkmm2ext/bindable_button.h	(revision 1765)
+++ libs/gtkmm2ext/gtkmm2ext/bindable_button.h	(working copy)
@@ -47,7 +47,8 @@
 			return true;
 		}
 	}
-
+	
+	PBD::Controllable* get_controllable() { return binding_proxy.get_controllable(); }
   private:
 	BindingProxy binding_proxy;
 };
@@ -71,6 +72,8 @@
 		}
 	}
 
+	PBD::Controllable* get_controllable() { return binding_proxy.get_controllable(); }
+
   private:
 	BindingProxy binding_proxy;
 };
Index: libs/gtkmm2ext/gtkmm2ext/barcontroller.h
===================================================================
--- libs/gtkmm2ext/gtkmm2ext/barcontroller.h	(revision 1765)
+++ libs/gtkmm2ext/gtkmm2ext/barcontroller.h	(working copy)
@@ -59,6 +59,7 @@
 	/* export this to allow direct connection to button events */
 
 	Gtk::Widget& event_widget() { return darea; }
+	PBD::Controllable* get_controllable() { return binding_proxy.get_controllable(); }
 
   protected:
 	Gtk::Adjustment&    adjustment;
Index: libs/gtkmm2ext/gtkmm2ext/binding_proxy.h
===================================================================
--- libs/gtkmm2ext/gtkmm2ext/binding_proxy.h	(revision 1765)
+++ libs/gtkmm2ext/gtkmm2ext/binding_proxy.h	(working copy)
@@ -40,6 +40,7 @@
 
 	bool button_press_handler (GdkEventButton *);
 
+	PBD::Controllable* get_controllable() { return &controllable; }
   protected:
 
 	Gtkmm2ext::PopUp     prompter;
Index: libs/ardour/ardour/session.h
===================================================================
--- libs/ardour/ardour/session.h	(revision 1765)
+++ libs/ardour/ardour/session.h	(working copy)
@@ -247,6 +247,9 @@
 	bool deletion_in_progress() const { return _state_of_the_state & Deletion; }
 	sigc::signal<void> DirtyChanged;
 
+	static sigc::signal<void> AutoBindingOn;
+	static sigc::signal<void> AutoBindingOff;
+
 	std::string sound_dir (bool with_path = true) const;
 	std::string peak_dir () const;
 	std::string dead_sound_dir () const;
Index: libs/ardour/session.cc
===================================================================
--- libs/ardour/session.cc	(revision 1765)
+++ libs/ardour/session.cc	(working copy)
@@ -107,6 +107,10 @@
 sigc::signal<void> Session::StartTimeChanged;
 sigc::signal<void> Session::EndTimeChanged;
 
+sigc::signal<void> Session::AutoBindingOn;
+sigc::signal<void> Session::AutoBindingOff;
+
+
 int
 Session::find_session (string str, string& path, string& snapshot, bool& isnew)
 {
Index: libs/pbd/controllable.cc
===================================================================
--- libs/pbd/controllable.cc	(revision 1765)
+++ libs/pbd/controllable.cc	(working copy)
@@ -28,6 +28,8 @@
 sigc::signal<void,Controllable*> Controllable::Destroyed;
 sigc::signal<bool,Controllable*> Controllable::StartLearning;
 sigc::signal<void,Controllable*> Controllable::StopLearning;
+sigc::signal<void,Controllable*,int,int> Controllable::CreateBinding;
+sigc::signal<void,Controllable*> Controllable::DeleteBinding;
 
 Glib::Mutex* Controllable::registry_lock = 0;
 Controllable::Controllables Controllable::registry;
Index: libs/pbd/pbd/controllable.h
===================================================================
--- libs/pbd/pbd/controllable.h	(revision 1765)
+++ libs/pbd/pbd/controllable.h	(working copy)
@@ -43,6 +43,8 @@
 	virtual bool can_send_feedback() const { return true; }
 
 	sigc::signal<void> LearningFinished;
+	static sigc::signal<void,PBD::Controllable*,int,int> CreateBinding;
+	static sigc::signal<void,PBD::Controllable*> DeleteBinding;
 
 	static sigc::signal<bool,PBD::Controllable*> StartLearning;
 	static sigc::signal<void,PBD::Controllable*> StopLearning;
Index: libs/surfaces/tranzport/io_usb.cc
===================================================================
--- libs/surfaces/tranzport/io_usb.cc	(revision 1765)
+++ libs/surfaces/tranzport/io_usb.cc	(working copy)
@@ -137,7 +137,7 @@
 
 int TranzportControlProtocol::read(uint8_t *buf, uint32_t timeout_override) 
 {
-	last_read_error = usb_interrupt_read (udev, READ_ENDPOINT, (char *) buf, 8, timeout_override);
+  last_read_error = 0; //usb_interrupt_read (udev, READ_ENDPOINT, (char *) buf, 8, timeout_override);
 	switch(last_read_error) {
 	case -ENOENT:
 	case -ENXIO:
@@ -164,7 +164,7 @@
 {
 	int val;
 	if(inflight > MAX_TRANZPORT_INFLIGHT) { return (-1); }
-	val = usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout);
+	val = 0;//usb_interrupt_write (udev, WRITE_ENDPOINT, (char*) cmd, 8, timeout_override ? timeout_override : timeout);
 
 	if (val < 0 && val !=8) {
 #if DEBUG_TRANZPORT
Index: libs/surfaces/generic_midi/generic_midi_control_protocol.cc
===================================================================
--- libs/surfaces/generic_midi/generic_midi_control_protocol.cc	(revision 1765)
+++ libs/surfaces/generic_midi/generic_midi_control_protocol.cc	(working copy)
@@ -57,9 +57,17 @@
 	_feedback_interval = 10000; // microseconds
 	last_feedback_time = 0;
 
+	auto_binding = FALSE;
+
 	Controllable::StartLearning.connect (mem_fun (*this, &GenericMidiControlProtocol::start_learning));
 	Controllable::StopLearning.connect (mem_fun (*this, &GenericMidiControlProtocol::stop_learning));
 	Session::SendFeedback.connect (mem_fun (*this, &GenericMidiControlProtocol::send_feedback));
+	
+	Controllable::CreateBinding.connect (mem_fun (*this, &GenericMidiControlProtocol::create_binding));
+	Controllable::DeleteBinding.connect (mem_fun (*this, &GenericMidiControlProtocol::delete_binding));
+
+	Session::AutoBindingOn.connect (mem_fun (*this, &GenericMidiControlProtocol::auto_binding_on));
+	Session::AutoBindingOff.connect (mem_fun (*this, &GenericMidiControlProtocol::auto_binding_off));
 }
 
 GenericMidiControlProtocol::~GenericMidiControlProtocol ()
@@ -226,6 +234,71 @@
 	}
 }
 
+void
+GenericMidiControlProtocol::delete_binding ( PBD::Controllable* control )
+{
+	if( control != 0 ) {
+		Glib::Mutex::Lock lm2 (controllables_lock);
+		
+		for( MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ++iter) {
+			MIDIControllable* existingBinding = (*iter);
+			
+			if( control == &(existingBinding->get_controllable()) ) {
+				delete existingBinding;
+				controllables.erase (iter);
+			}
+			
+		} // end for midi controllables
+	} // end null check
+}
+void
+GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos, int control_number)
+{
+	if( control != NULL ) {
+		Glib::Mutex::Lock lm2 (controllables_lock);
+		
+		MIDI::channel_t channel = (pos & 0xf);
+		MIDI::byte value = control_number;
+		
+		// Create a MIDIControllable::
+		MIDIControllable* mc = new MIDIControllable (*_port, *control);
+		
+		// Remove any old binding for this midi channel/type/value pair
+		// Note:  can't use delete_binding() here because we don't know the specific controllable we want to remove, only the midi information
+		for( MIDIControllables::iterator iter = controllables.begin(); iter != controllables.end(); ++iter) {
+			MIDIControllable* existingBinding = (*iter);
+			
+			if( (existingBinding->get_control_channel() & 0xf ) == channel &&
+			    existingBinding->get_control_additional() == value &&
+			    (existingBinding->get_control_type() & 0xf0 ) == MIDI::controller ) {
+				
+				delete existingBinding;
+				controllables.erase (iter);
+			}
+			
+		} // end for midi controllables
+		
+		
+		// Update the MIDI Controllable based on the the pos param
+		// Here is where a table lookup for user mappings could go; for now we'll just wing it...
+		mc->bind_midi( channel, MIDI::controller, value );
+		
+		controllables.insert (mc);
+	} // end null test
+}
+
+void
+GenericMidiControlProtocol::auto_binding_on()
+{
+	auto_binding = TRUE;
+}
+
+void
+GenericMidiControlProtocol::auto_binding_off()
+{
+	auto_binding = FALSE;
+}
+
 XMLNode&
 GenericMidiControlProtocol::get_state () 
 {
@@ -270,46 +343,47 @@
 		_feedback_interval = 10000;
 	}
 
-	Controllable* c;
+	// Are we using the autobinding feature?  If so skip this part
+	if ( !auto_binding ) {
+		
+		Controllable* c;
+		
+		{
+			Glib::Mutex::Lock lm (pending_lock);
+			pending_controllables.clear ();
+		}
+		
+		Glib::Mutex::Lock lm2 (controllables_lock);
+		controllables.clear ();
+		nlist = node.children(); // "controls"
+		
+		if (nlist.empty()) {
+			return 0;
+		}
+		
+		nlist = nlist.front()->children ();
+		
+		for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
+			
+			if ((prop = (*niter)->property ("id")) != 0) {
 
-	{
-		Glib::Mutex::Lock lm (pending_lock);
-		pending_controllables.clear ();
-	}
-
-	Glib::Mutex::Lock lm2 (controllables_lock);
-
-	controllables.clear ();
-
-	nlist = node.children(); // "controls"
-
-	if (nlist.empty()) {
-		return 0;
-	}
-
-	nlist = nlist.front()->children ();
-
-	for (niter = nlist.begin(); niter != nlist.end(); ++niter) {
-
-		if ((prop = (*niter)->property ("id")) != 0) {
-			
-			ID id = prop->value ();
-			
-			c = Controllable::by_id (id);
-			
-			if (c) {
-				MIDIControllable* mc = new MIDIControllable (*_port, *c);
-				if (mc->set_state (**niter) == 0) {
-					controllables.insert (mc);
+				ID id = prop->value ();
+				c = session->controllable_by_id (id);
+				
+				if (c) {
+					MIDIControllable* mc = new MIDIControllable (*_port, *c);
+					if (mc->set_state (**niter) == 0) {
+						controllables.insert (mc);
+					}
+					
+				} else {
+					warning << string_compose (_("Generic MIDI control: controllable %1 not found in session (ignored)"),
+								   id)
+						<< endmsg;
 				}
-				
-			} else {
-				warning << string_compose (_("Generic MIDI control: controllable %1 not found (ignored)"), id)
-					<< endmsg;
 			}
 		}
-	}
-
+	} // end autobinding check
 	return 0;
 }
 
Index: libs/surfaces/generic_midi/generic_midi_control_protocol.h
===================================================================
--- libs/surfaces/generic_midi/generic_midi_control_protocol.h	(revision 1765)
+++ libs/surfaces/generic_midi/generic_midi_control_protocol.h	(working copy)
@@ -44,6 +44,7 @@
 	ARDOUR::microseconds_t last_feedback_time;
 
 	bool  do_feedback;
+	bool  auto_binding;
 	void _send_feedback ();
 	void  send_feedback ();
 
@@ -59,6 +60,13 @@
 	void stop_learning (PBD::Controllable*);
 
 	void learning_stopped (MIDIControllable*);
+
+	void create_binding (PBD::Controllable*, int, int);
+	void delete_binding (PBD::Controllable*);
+
+	void auto_binding_on();
+	void auto_binding_off();
+
 };
 
 #endif /* ardour_generic_midi_control_protocol_h */
Index: libs/surfaces/generic_midi/midicontrollable.h
===================================================================
--- libs/surfaces/generic_midi/midicontrollable.h	(revision 1765)
+++ libs/surfaces/generic_midi/midicontrollable.h	(working copy)
@@ -63,6 +63,10 @@
 	XMLNode& get_state (void);
 	int set_state (const XMLNode&);
 
+	void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte);
+	MIDI::channel_t get_control_channel () { return control_channel; }
+	MIDI::eventType get_control_type () { return control_type; }
+	MIDI::byte get_control_additional () { return control_additional; }
   private:
 	PBD::Controllable& controllable;
 	MIDI::Port&     _port;
@@ -86,8 +90,6 @@
 	void midi_sense_controller (MIDI::Parser &, MIDI::EventTwoBytes *);
 	void midi_sense_program_change (MIDI::Parser &, MIDI::byte);
 	void midi_sense_pitchbend (MIDI::Parser &, MIDI::pitchbend_t);
-
-	void bind_midi (MIDI::channel_t, MIDI::eventType, MIDI::byte);
 };
 
 #endif // __gm_midicontrollable_h__
