[SCM] ardour3/upstream: Imported Upstream version 3.5.143~dfsg

adiknoth-guest at users.alioth.debian.org adiknoth-guest at users.alioth.debian.org
Mon Dec 23 22:03:14 UTC 2013


The following commit has been merged in the upstream branch:
commit 84d550e52ab9a80e06f7c183d01bc8b4360e2b52
Author: Adrian Knoth <adi at drcomp.erfurt.thur.de>
Date:   Mon Dec 23 21:28:33 2013 +0100

    Imported Upstream version 3.5.143~dfsg

diff --git a/doc/updating_waf.txt b/doc/updating_waf.txt
index 4030d07..622a0f6 100644
--- a/doc/updating_waf.txt
+++ b/doc/updating_waf.txt
@@ -1,5 +1,5 @@
 Download waf (http://code.google.com/p/waf/)
-Download autowaf (http://svn.drobilla.net/autowaf)
+autowaf.py is present in the tools directory of the Ardour source code.
 
 From within the waf source tree, run:
 
diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
index 010f7d3..6824ecf 100644
--- a/gtk2_ardour/ardour_ui.cc
+++ b/gtk2_ardour/ardour_ui.cc
@@ -1213,7 +1213,7 @@ ARDOUR_UI::update_cpu_load ()
 	   should also be changed.
 	*/
 
-	float const c = AudioEngine::instance()->get_cpu_load ();
+	float const c = AudioEngine::instance()->get_dsp_load ();
 	snprintf (buf, sizeof (buf), _("DSP: <span foreground=\"%s\">%5.1f%%</span>"), c >= 90 ? X_("red") : X_("green"), c);
 	cpu_load_label.set_markup (buf);
 }
@@ -2190,8 +2190,13 @@ ARDOUR_UI::snapshot_session (bool switch_to_it)
 
 	prompter.set_name ("Prompter");
 	prompter.add_button (Gtk::Stock::SAVE, Gtk::RESPONSE_ACCEPT);
-	prompter.set_title (_("Take Snapshot"));
-	prompter.set_prompt (_("Name of new snapshot"));
+	if (switch_to_it) {
+		prompter.set_title (_("Save as..."));
+		prompter.set_prompt (_("New session name"));
+	} else {
+		prompter.set_title (_("Take Snapshot"));
+		prompter.set_prompt (_("Name of new snapshot"));
+	}
 
 	if (!switch_to_it) {
 		char timebuf[128];
diff --git a/gtk2_ardour/ardour_ui_dialogs.cc b/gtk2_ardour/ardour_ui_dialogs.cc
index 2ad4cd3..b0ac528 100644
--- a/gtk2_ardour/ardour_ui_dialogs.cc
+++ b/gtk2_ardour/ardour_ui_dialogs.cc
@@ -186,6 +186,11 @@ ARDOUR_UI::set_session (Session *s)
 
 	update_format ();
 
+	if (meter_box.get_parent()) {
+		transport_tearoff_hbox.remove (meter_box);
+		transport_tearoff_hbox.remove (editor_meter_peak_display);
+	}
+
 	if (editor_meter) {
 		meter_box.remove(*editor_meter);
 		delete editor_meter;
@@ -193,7 +198,9 @@ ARDOUR_UI::set_session (Session *s)
 		editor_meter_peak_display.hide();
 	}
 
-	if (_session && _session->master_out()) {
+	if (_session
+			&& _session->master_out()
+			&& _session->master_out()->n_outputs().n(DataType::AUDIO) > 0) {
 		editor_meter = new LevelMeterHBox(_session);
 		editor_meter->set_meter (_session->master_out()->shared_peak_meter().get());
 		editor_meter->clear_meters();
@@ -216,14 +223,12 @@ ARDOUR_UI::set_session (Session *s)
 		editor_meter_peak_display.signal_button_release_event().connect (sigc::mem_fun(*this, &ARDOUR_UI::editor_meter_peak_button_release), false);
 
 		if (Config->get_show_editor_meter()) {
+			transport_tearoff_hbox.pack_start (meter_box, false, false);
+			transport_tearoff_hbox.pack_start (editor_meter_peak_display, false, false);
 			meter_box.show();
 			editor_meter_peak_display.show();
-		} else {
-			meter_box.hide();
-			editor_meter_peak_display.hide();
 		}
-	}
-
+	} 
 }
 
 int
diff --git a/gtk2_ardour/ardour_ui_options.cc b/gtk2_ardour/ardour_ui_options.cc
index 0e28900..423b685 100644
--- a/gtk2_ardour/ardour_ui_options.cc
+++ b/gtk2_ardour/ardour_ui_options.cc
@@ -401,12 +401,19 @@ ARDOUR_UI::parameter_changed (std::string p)
 		start_clocking ();
 	} else if (p == "show-editor-meter") {
 		bool show = Config->get_show_editor_meter();
-		if (editor_meter && show) {
-			meter_box.show();
-			editor_meter_peak_display.show();
-		} else if (editor_meter && !show) {
-			meter_box.hide();
-			editor_meter_peak_display.hide();
+
+		if (editor_meter) {
+			if (meter_box.get_parent()) {
+				transport_tearoff_hbox.remove (meter_box);
+				transport_tearoff_hbox.remove (editor_meter_peak_display);
+			}
+
+			if (show) {
+				transport_tearoff_hbox.pack_start (meter_box, false, false);
+				transport_tearoff_hbox.pack_start (editor_meter_peak_display, false, false);
+				meter_box.show();
+				editor_meter_peak_display.show();
+			} 
 		}
 	}
 }
diff --git a/gtk2_ardour/audio_clock.cc b/gtk2_ardour/audio_clock.cc
index 6680e95..b24d22f 100644
--- a/gtk2_ardour/audio_clock.cc
+++ b/gtk2_ardour/audio_clock.cc
@@ -620,6 +620,9 @@ AudioClock::end_edit (bool modify)
 			break;
 
 		case Frames:
+			if (edit_string.length() < 1) {
+				edit_string = pre_edit_string;
+			}
 			break;
 		}
 
diff --git a/gtk2_ardour/editor_regions.cc b/gtk2_ardour/editor_regions.cc
index 72a0da2..bf13bd5 100644
--- a/gtk2_ardour/editor_regions.cc
+++ b/gtk2_ardour/editor_regions.cc
@@ -1115,7 +1115,7 @@ EditorRegions::sorter (TreeModel::iterator a, TreeModel::iterator b)
 
 	switch (_sort_type) {
 	case ByName:
-		cmp = g_strcasecmp (region1->name().c_str(), region2->name().c_str());
+		cmp = region1->name().compare(region2->name());
 		break;
 
 	case ByLength:
@@ -1140,7 +1140,7 @@ EditorRegions::sorter (TreeModel::iterator a, TreeModel::iterator b)
 		break;
 
 	case BySourceFileName:
-		cmp = g_strcasecmp (region1->source()->name().c_str(), region2->source()->name().c_str());
+		cmp = region1->source()->name().compare(region2->source()->name());
 		break;
 
 	case BySourceFileLength:
@@ -1153,9 +1153,9 @@ EditorRegions::sorter (TreeModel::iterator a, TreeModel::iterator b)
 
 	case BySourceFileFS:
 		if (region1->source()->name() == region2->source()->name()) {
-			cmp = g_strcasecmp (region1->name().c_str(),  region2->name().c_str());
+			cmp = region1->name().compare(region2->name());
 		} else {
-			cmp = g_strcasecmp (region1->source()->name().c_str(),  region2->source()->name().c_str());
+			cmp = region1->source()->name().compare(region2->source()->name());
 		}
 		break;
 	}
diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc
index 37c29f4..d438ff8 100644
--- a/gtk2_ardour/engine_dialog.cc
+++ b/gtk2_ardour/engine_dialog.cc
@@ -87,7 +87,6 @@ EngineControl::EngineControl ()
 	, midi_refresh_button (_("Refresh list"))
 	, ignore_changes (0)
 	, _desired_sample_rate (0)
-	, no_push (true)
 	, started_at_least_once (false)
 {
 	using namespace Notebook_Helpers;
@@ -290,8 +289,6 @@ EngineControl::EngineControl ()
 	output_channels.signal_changed().connect (sigc::mem_fun (*this, &EngineControl::parameter_changed));
 
 	notebook.signal_switch_page().connect (sigc::mem_fun (*this, &EngineControl::on_switch_page));
-
-	no_push = false;
  }
 
  void
@@ -874,10 +871,6 @@ EngineControl::EngineControl ()
 	 /* pick up any saved state for this device */
 
 	 maybe_display_saved_state ();
-
-	 /* and push it to the backend */
-
-	 push_state_to_backend (false);
  }	
 
  string
@@ -1207,14 +1200,9 @@ EngineControl::EngineControl ()
 	 }
  }
 
-
  int
  EngineControl::push_state_to_backend (bool start)
  {
-	 if (no_push) {
-		 return 0;
-	 }
-
 	 boost::shared_ptr<ARDOUR::AudioBackend> backend = ARDOUR::AudioEngine::instance()->current_backend();
 
 	 if (!backend) {
diff --git a/gtk2_ardour/engine_dialog.h b/gtk2_ardour/engine_dialog.h
index 31648b6..6d10eb7 100644
--- a/gtk2_ardour/engine_dialog.h
+++ b/gtk2_ardour/engine_dialog.h
@@ -114,7 +114,6 @@ class EngineControl : public ArdourDialog, public PBD::ScopedConnectionList {
     
     uint32_t ignore_changes;
     uint32_t _desired_sample_rate;
-    bool     no_push;
     bool     started_at_least_once;
 
     void driver_changed ();
diff --git a/gtk2_ardour/export_dialog.cc b/gtk2_ardour/export_dialog.cc
index a64acd1..1458747 100644
--- a/gtk2_ardour/export_dialog.cc
+++ b/gtk2_ardour/export_dialog.cc
@@ -215,9 +215,9 @@ ExportDialog::init_components ()
 }
 
 void
-ExportDialog::notify_errors ()
+ExportDialog::notify_errors (bool force)
 {
-	if (status->errors()) {
+	if (force || status->errors()) {
 		std::string txt = _("Export has been aborted due to an error!\nSee the Log for details.");
 		Gtk::MessageDialog msg (txt, false, Gtk::MESSAGE_ERROR, Gtk::BUTTONS_OK, true);
 		msg.run();
@@ -303,9 +303,14 @@ ExportDialog::show_conflicting_files ()
 void
 ExportDialog::do_export ()
 {
-	profile_manager->prepare_for_export ();
-	handler->do_export ();
-	show_progress ();
+	try {
+		profile_manager->prepare_for_export ();
+		handler->do_export ();
+		show_progress ();
+	} catch(std::exception & e) {
+		error << string_compose (_("Export initialization failed: %1"), e.what()) << endmsg;
+		notify_errors(true);
+	}
 }
 
 void
diff --git a/gtk2_ardour/export_dialog.h b/gtk2_ardour/export_dialog.h
index 52c5366..756a3e7 100644
--- a/gtk2_ardour/export_dialog.h
+++ b/gtk2_ardour/export_dialog.h
@@ -95,7 +95,7 @@ class ExportDialog : public ArdourDialog {
 
 	void expanded_changed();
 
-	void notify_errors ();
+	void notify_errors (bool force = false);
 	void close_dialog ();
 
 	void sync_with_manager ();
diff --git a/gtk2_ardour/gain_meter.h b/gtk2_ardour/gain_meter.h
index 8286cbe..b71469b 100644
--- a/gtk2_ardour/gain_meter.h
+++ b/gtk2_ardour/gain_meter.h
@@ -101,6 +101,7 @@ class GainMeterBase : virtual public sigc::trackable, ARDOUR::SessionHandlePtr
 
 	friend class MixerStrip;
 	friend class MeterStrip;
+	friend class RouteTimeAxisView;
 	boost::shared_ptr<ARDOUR::Route> _route;
 	boost::shared_ptr<ARDOUR::PeakMeter> _meter;
 	boost::shared_ptr<ARDOUR::Amp> _amp;
diff --git a/gtk2_ardour/gtk_pianokeyboard.c b/gtk2_ardour/gtk_pianokeyboard.c
index f3897e3..4f1740f 100644
--- a/gtk2_ardour/gtk_pianokeyboard.c
+++ b/gtk2_ardour/gtk_pianokeyboard.c
@@ -732,13 +732,13 @@ piano_keyboard_set_keyboard_layout(PianoKeyboard *pk, const char *layout)
 {
 	assert(layout);
 
-	if (!g_strcasecmp(layout, "QWERTY")) {
+	if (!g_ascii_strcasecmp(layout, "QWERTY")) {
 		bind_keys_qwerty(pk);
 
-	} else if (!g_strcasecmp(layout, "QWERTZ")) {
+	} else if (!g_ascii_strcasecmp(layout, "QWERTZ")) {
 		bind_keys_qwertz(pk);
 
-	} else if (!g_strcasecmp(layout, "AZERTY")) {
+	} else if (!g_ascii_strcasecmp(layout, "AZERTY")) {
 		bind_keys_azerty(pk);
 
 	} else {
diff --git a/gtk2_ardour/level_meter.cc b/gtk2_ardour/level_meter.cc
index bf98235..493a08b 100644
--- a/gtk2_ardour/level_meter.cc
+++ b/gtk2_ardour/level_meter.cc
@@ -157,6 +157,8 @@ LevelMeterBase::update_meters ()
 					(*i).meter->set (meter_deflect_ppm (peak + meter_lineup(0)));
 				} else if (meter_type == MeterVU) {
 					(*i).meter->set (meter_deflect_vu (peak + vu_standard() + meter_lineup(0)));
+				} else if (meter_type == MeterK12) {
+					(*i).meter->set (meter_deflect_k (peak, 12), meter_deflect_k(_meter->meter_level(n, MeterPeak), 12));
 				} else if (meter_type == MeterK14) {
 					(*i).meter->set (meter_deflect_k (peak, 14), meter_deflect_k(_meter->meter_level(n, MeterPeak), 14));
 				} else if (meter_type == MeterK20) {
@@ -320,6 +322,17 @@ LevelMeterBase::setup_meters (int len, int initial_width, int thin_width)
 					c[6] = c[7] = 0xffff00ff;
 					c[8] = c[9] = 0xff0000ff;
 					break;
+				case MeterK12:
+					stp[0] = 115.0 * meter_deflect_k(-32, 12);  //-20
+					stp[1] = 115.0 * meter_deflect_k(-12, 12);  //  0
+					stp[2] = 115.0 * meter_deflect_k(-10, 12);  // +2
+					stp[3] = 115.0 * meter_deflect_k( -8, 12);  // +4
+					c[0] = c[1] = 0x008800ff;
+					c[2] = c[3] = 0x00ff00ff;
+					c[4] = c[5] = 0xffff00ff;
+					c[6] = c[7] = 0xffff00ff;
+					c[8] = c[9] = 0xff0000ff;
+					break;
 				case MeterIEC2BBC:
 					c[0] = c[1] = c[2] = c[3] = c[4] = c[5] = c[6] = c[7] = c[8] = c[9] =
 						ARDOUR_UI::config()->color_by_name ("meter color BBC");
diff --git a/gtk2_ardour/meter_patterns.cc b/gtk2_ardour/meter_patterns.cc
index f392dc0..7db2924 100644
--- a/gtk2_ardour/meter_patterns.cc
+++ b/gtk2_ardour/meter_patterns.cc
@@ -101,6 +101,9 @@ ArdourMeter::meter_type_string (ARDOUR::MeterType mt)
 		case MeterK14:
 			return _("K14");
 			break;
+		case MeterK12:
+			return _("K12");
+			break;
 		case MeterVU:
 			return _("VU");
 			break;
@@ -199,6 +202,16 @@ static inline float mtr_col_and_fract(
 			}
 			fraction = meter_deflect_k (val, 14);
 			break;
+		case MeterK12:
+			if (val >= -8.0) {
+				cairo_set_source_rgb (cr, 1.0, 0.0, 0.0); // red
+			} else if (val >= -12.0) {
+				cairo_set_source_rgb (cr, 0.8, 0.8, 0.0); // yellow
+			} else {
+				cairo_set_source_rgb (cr, 0.0, 1.0, 0.0); // green
+			}
+			fraction = meter_deflect_k (val, 12);
+			break;
 	}
 	return fraction;
 }
@@ -226,6 +239,7 @@ static void set_bg_color(Gtk::Widget& w, cairo_t* cr, MeterType type) {
 		case MeterIEC1NOR:
 		case MeterIEC2BBC:
 		case MeterIEC2EBU:
+		case MeterK12:
 		case MeterK14:
 		case MeterK20:
 			if (rgba_p_from_style("meterstripPPM", &r, &g, &b, "bg")) {
@@ -334,6 +348,20 @@ meter_render_ticks (Gtk::Widget& w, MeterType type, vector<ARDOUR::DataType> typ
 		case DataType::AUDIO:
 
 			switch (type) {
+				case MeterK12:
+					points.insert (std::pair<float,float>(-52.0f, 1.0));
+					points.insert (std::pair<float,float>(-42.0f, 1.0));
+					points.insert (std::pair<float,float>(-32.0f, 1.0));
+					points.insert (std::pair<float,float>(-22.0f, 1.0));
+					points.insert (std::pair<float,float>(-18.0f, 1.0));
+					points.insert (std::pair<float,float>(-15.0f, 1.0));
+					points.insert (std::pair<float,float>(-12.0f, 1.0));
+					points.insert (std::pair<float,float>( -9.0f, 1.0));
+					points.insert (std::pair<float,float>( -8.0f, 0.8));
+					points.insert (std::pair<float,float>( -6.0f, 1.0));
+					points.insert (std::pair<float,float>( -3.0f, 1.0));
+					points.insert (std::pair<float,float>(  0.0f, 1.0));
+					break;
 				case MeterK14:
 					points.insert (std::pair<float,float>(-54.0f, 1.0));
 					points.insert (std::pair<float,float>(-44.0f, 1.0));
@@ -645,6 +673,20 @@ meter_render_metrics (Gtk::Widget& w, MeterType type, vector<DataType> types)
 		case DataType::AUDIO:
 			layout->set_attributes (audio_font_attributes);
 			switch (type) {
+				case MeterK12:
+					overlay_midi = 0;
+					points.insert (std::pair<float,string>(-52.0f, "-40"));
+					points.insert (std::pair<float,string>(-42.0f, "-30"));
+					points.insert (std::pair<float,string>(-32.0f, "-20"));
+					points.insert (std::pair<float,string>(-22.0f, "-10"));
+					points.insert (std::pair<float,string>(-18.0f,  "-6"));
+					points.insert (std::pair<float,string>(-15.0f,  "-3"));
+					points.insert (std::pair<float,string>(-12.0f,  " 0"));
+					points.insert (std::pair<float,string>( -9.0f,  "+3"));
+					points.insert (std::pair<float,string>( -6.0f,  "+6"));
+					points.insert (std::pair<float,string>( -3.0f,  "+9"));
+					points.insert (std::pair<float,string>(  0.0f, "+12"));
+					break;
 				case MeterK14:
 					overlay_midi = 0;
 					points.insert (std::pair<float,string>(-54.0f, "-40"));
@@ -903,6 +945,9 @@ meter_render_metrics (Gtk::Widget& w, MeterType type, vector<DataType> types)
 					case MeterK14:
 						layout->set_text("K14");
 						break;
+					case MeterK12:
+						layout->set_text("K12");
+						break;
 					default:
 					case MeterPeak:
 					case MeterKrms:
diff --git a/gtk2_ardour/meter_strip.cc b/gtk2_ardour/meter_strip.cc
index 703870e..632c6ef 100644
--- a/gtk2_ardour/meter_strip.cc
+++ b/gtk2_ardour/meter_strip.cc
@@ -177,6 +177,11 @@ MeterStrip::MeterStrip (Session* sess, boost::shared_ptr<ARDOUR::Route> rt)
 	namebx.set_size_request(18, 52);
 	namebx.pack_start(name_label, true, false, 3);
 
+	mon_in_box.pack_start(*monitor_input_button, true, false);
+	btnbox.pack_start(mon_in_box, false, false, 1);
+	mon_disk_box.pack_start(*monitor_disk_button, true, false);
+	btnbox.pack_start(mon_disk_box, false, false, 1);
+
 	recbox.pack_start(*rec_enable_button, true, false);
 	btnbox.pack_start(recbox, false, false, 1);
 	mutebox.pack_start(*mute_button, true, false);
@@ -193,9 +198,17 @@ MeterStrip::MeterStrip (Session* sess, boost::shared_ptr<ARDOUR::Route> rt)
 	solo_button->set_corner_radius(2);
 	solo_button->set_size_request(16, 16);
 
+	monitor_input_button->set_corner_radius(2);
+	monitor_input_button->set_size_request(16, 16);
+
+	monitor_disk_button->set_corner_radius(2);
+	monitor_disk_button->set_size_request(16, 16);
+
 	mutebox.set_size_request(16, 16);
 	solobox.set_size_request(16, 16);
 	recbox.set_size_request(16, 16);
+	mon_in_box.set_size_request(16, 16);
+	mon_disk_box.set_size_request(16, 16);
 	spacer.set_size_request(-1,0);
 
 	update_button_box();
@@ -232,6 +245,8 @@ MeterStrip::MeterStrip (Session* sess, boost::shared_ptr<ARDOUR::Route> rt)
 	mtr_container.show();
 	mtr_hsep.show();
 	nfo_vbox.show();
+	monitor_input_button->show();
+	monitor_disk_button->show();
 
 	_route->shared_peak_meter()->ConfigurationChanged.connect (
 			route_connections, invalidator (*this), boost::bind (&MeterStrip::meter_configuration_changed, this, _1), gui_context()
@@ -339,6 +354,8 @@ MeterStrip::set_button_names()
 		}
 	}
 
+	monitor_input_button->set_text (_("I"));
+	monitor_disk_button->set_text (_("D"));
 }
 
 void
@@ -545,6 +562,7 @@ MeterStrip::update_background(MeterType type)
 		case MeterIEC1NOR:
 		case MeterIEC2BBC:
 		case MeterIEC2EBU:
+		case MeterK12:
 		case MeterK14:
 		case MeterK20:
 			mtr_container.set_name ("meterstripPPM");
@@ -651,6 +669,14 @@ MeterStrip::update_button_box ()
 	} else {
 		recbox.hide();
 	}
+	if (_session->config.get_show_monitor_on_meterbridge()) {
+		height += 18 + 18;
+		mon_in_box.show();
+		mon_disk_box.show();
+	} else {
+		mon_in_box.hide();
+		mon_disk_box.hide();
+	}
 	btnbox.set_size_request(16, height);
 	check_resize();
 }
@@ -684,6 +710,9 @@ MeterStrip::parameter_changed (std::string const & p)
 	else if (p == "show-name-on-meterbridge") {
 		update_name_box();
 	}
+	else if (p == "show-monitor-on-meterbridge") {
+		update_button_box();
+	}
 	else if (p == "meterbridge-label-height") {
 		queue_resize();
 	}
@@ -719,6 +748,7 @@ MeterStrip::popup_level_meter_menu (GdkEventButton* ev)
 	add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
 	add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK20), MeterK20);
 	add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK14), MeterK14);
+	add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterK12), MeterK12);
 	add_level_meter_type_item (items, group, ArdourMeter::meter_type_string(MeterVU),  MeterVU);
 
 	MeterType cmt = _route->meter_type();
diff --git a/gtk2_ardour/meter_strip.h b/gtk2_ardour/meter_strip.h
index e817f7d..e1bae71 100644
--- a/gtk2_ardour/meter_strip.h
+++ b/gtk2_ardour/meter_strip.h
@@ -108,6 +108,8 @@ class MeterStrip : public Gtk::VBox, public RouteUI
 	Gtk::HBox mutebox;
 	Gtk::HBox solobox;
 	Gtk::HBox recbox;
+	Gtk::HBox mon_in_box;
+	Gtk::HBox mon_disk_box;
 
 	Gtk::Alignment meter_align;
 	Gtk::Alignment peak_align;
diff --git a/gtk2_ardour/mixer_strip.cc b/gtk2_ardour/mixer_strip.cc
index 5059437..aa49e20 100644
--- a/gtk2_ardour/mixer_strip.cc
+++ b/gtk2_ardour/mixer_strip.cc
@@ -2141,6 +2141,7 @@ MixerStrip::popup_level_meter_menu (GdkEventButton* ev)
 	add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterIEC2EBU), MeterIEC2EBU);
 	add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterK20), MeterK20);
 	add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterK14), MeterK14);
+	add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterK12), MeterK12);
 	add_level_meter_item_type (items, tgroup, ArdourMeter::meter_type_string(MeterVU),  MeterVU);
 
 	int _strip_type;
diff --git a/gtk2_ardour/plugin_selector.cc b/gtk2_ardour/plugin_selector.cc
index ebfcc67..bb96c7f 100644
--- a/gtk2_ardour/plugin_selector.cc
+++ b/gtk2_ardour/plugin_selector.cc
@@ -37,6 +37,7 @@
 
 #include "ardour/plugin_manager.h"
 #include "ardour/plugin.h"
+#include "ardour/utils.h"
 
 #include "ardour_ui.h"
 #include "plugin_selector.h"
@@ -538,13 +539,13 @@ struct PluginMenuCompareByCreator {
     bool operator() (PluginInfoPtr a, PluginInfoPtr b) const {
 	    int cmp;
 
-	    cmp = g_strcasecmp (a->creator.c_str(), b->creator.c_str());
+	    cmp = cmp_nocase_utf8 (a->creator, b->creator);
 
 	    if (cmp < 0) {
 		    return true;
 	    } else if (cmp == 0) {
 		    /* same creator ... compare names */
-		    if (g_strcasecmp (a->name.c_str(), b->name.c_str()) < 0) {
+		    if (cmp_nocase_utf8 (a->name, b->name) < 0) {
 			    return true;
 		    }
 	    }
@@ -556,7 +557,7 @@ struct PluginMenuCompareByName {
     bool operator() (PluginInfoPtr a, PluginInfoPtr b) const {
 	    int cmp;
 
-	    cmp = g_strcasecmp (a->name.c_str(), b->name.c_str());
+	    cmp = cmp_nocase_utf8 (a->name, b->name);
 
 	    if (cmp < 0) {
 		    return true;
@@ -574,13 +575,13 @@ struct PluginMenuCompareByCategory {
     bool operator() (PluginInfoPtr a, PluginInfoPtr b) const {
 	    int cmp;
 
-	    cmp = g_strcasecmp (a->category.c_str(), b->category.c_str());
+	    cmp = cmp_nocase_utf8 (a->category, b->category);
 
 	    if (cmp < 0) {
 		    return true;
 	    } else if (cmp == 0) {
 		    /* same category ... compare names */
-		    if (g_strcasecmp (a->name.c_str(), b->name.c_str()) < 0) {
+		    if (cmp_nocase_utf8 (a->name, b->name) < 0) {
 			    return true;
 		    }
 	    }
diff --git a/gtk2_ardour/port_group.cc b/gtk2_ardour/port_group.cc
index 213c818..cafcaad 100644
--- a/gtk2_ardour/port_group.cc
+++ b/gtk2_ardour/port_group.cc
@@ -438,7 +438,7 @@ PortGroupList::gather (ARDOUR::Session* session, ARDOUR::DataType type, bool inp
 		ardour->add_bundle (ltc);
 	}
 
-	/* Ardour's surfaces */
+	/* Ardour's control surfaces */
 
 	ControlProtocolManager& m = ControlProtocolManager::instance ();
 	for (list<ControlProtocolInfo*>::iterator i = m.control_protocol_info.begin(); i != m.control_protocol_info.end(); ++i) {
diff --git a/gtk2_ardour/processor_box.cc b/gtk2_ardour/processor_box.cc
index a22e991..b549fd1 100644
--- a/gtk2_ardour/processor_box.cc
+++ b/gtk2_ardour/processor_box.cc
@@ -2598,7 +2598,7 @@ ProcessorBox::generate_processor_title (boost::shared_ptr<PluginInsert> pi)
 	if (owner) {
 		return string_compose(_("%1: %2 (by %3)"), owner->name(), pi->name(), maker);
 	} else {
-		return string_compose(_("%2 (by %3)"), pi->name(), maker);
+		return string_compose(_("%1 (by %2)"), pi->name(), maker);
 	}
 }
 
diff --git a/gtk2_ardour/rc_option_editor.cc b/gtk2_ardour/rc_option_editor.cc
index 43fd163..b514a75 100644
--- a/gtk2_ardour/rc_option_editor.cc
+++ b/gtk2_ardour/rc_option_editor.cc
@@ -648,6 +648,7 @@ class ControlSurfacesOptions : public OptionEditorBox
 public:
 	ControlSurfacesOptions (Gtk::Window& parent)
 		: _parent (parent)
+		, _ignore_view_change (0)
 	{
 		_store = ListStore::create (_model);
 		_view.set_model (_store);
@@ -700,9 +701,14 @@ private:
         void protocol_status_changed (ControlProtocolInfo* cpi) {
 		/* find the row */
 		TreeModel::Children rows = _store->children();
+		
 		for (TreeModel::Children::iterator x = rows.begin(); x != rows.end(); ++x) {
+			string n = ((*x)[_model.name]);
+
 			if ((*x)[_model.protocol_info] == cpi) {
+				_ignore_view_change++;
 				(*x)[_model.enabled] = (cpi->protocol || cpi->requested);
+				_ignore_view_change--;
 				break;
 			}
 		}
@@ -712,6 +718,10 @@ private:
 	{
 		TreeModel::Row r = *i;
 
+		if (_ignore_view_change) {
+			return;
+		}
+
 		ControlProtocolInfo* cpi = r[_model.protocol_info];
 		if (!cpi) {
 			return;
@@ -720,22 +730,23 @@ private:
 		bool const was_enabled = (cpi->protocol != 0);
 		bool const is_enabled = r[_model.enabled];
 
+
 		if (was_enabled != is_enabled) {
+
 			if (!was_enabled) {
-				ControlProtocolManager::instance().instantiate (*cpi);
+				ControlProtocolManager::instance().activate (*cpi);
 			} else {
 				Gtk::Window* win = r[_model.editor];
 				if (win) {
 					win->hide ();
 				}
 
-				ControlProtocolManager::instance().teardown (*cpi);
+				ControlProtocolManager::instance().deactivate (*cpi);
 					
 				if (win) {
 					delete win;
+					r[_model.editor] = 0;
 				}
-				r[_model.editor] = 0;
-				cpi->requested = false;
 			}
 		}
 
@@ -805,6 +816,7 @@ private:
 	TreeView _view;
         Gtk::Window& _parent;
         PBD::ScopedConnection protocol_status_connection;
+        uint32_t _ignore_view_change;
 };
 
 class VideoTimelineOptions : public OptionEditorBox
diff --git a/gtk2_ardour/route_time_axis.cc b/gtk2_ardour/route_time_axis.cc
index b0fec29..b777c30 100644
--- a/gtk2_ardour/route_time_axis.cc
+++ b/gtk2_ardour/route_time_axis.cc
@@ -2266,6 +2266,8 @@ RouteTimeAxisView::meter_changed ()
 	if (_route && !no_redraw) {
 		request_redraw ();
 	}
+	// reset peak when meter point changes
+	gm.reset_peak_display();
 }
 
 void
diff --git a/gtk2_ardour/session_option_editor.cc b/gtk2_ardour/session_option_editor.cc
index 60f575f..f243973 100644
--- a/gtk2_ardour/session_option_editor.cc
+++ b/gtk2_ardour/session_option_editor.cc
@@ -318,6 +318,13 @@ SessionOptionEditor::SessionOptionEditor (Session* s)
 			    sigc::mem_fun (*_session_config, &SessionConfiguration::set_show_solo_on_meterbridge)
 			    ));
 
+	add_option (_("Meterbridge"), new BoolOption (
+			    "show-monitor-on-meterbridge",
+			    _("Monitor Buttons"),
+			    sigc::mem_fun (*_session_config, &SessionConfiguration::get_show_monitor_on_meterbridge),
+			    sigc::mem_fun (*_session_config, &SessionConfiguration::set_show_monitor_on_meterbridge)
+			    ));
+
 	add_option (_("Meterbridge"), new OptionEditorHeading (_("Name Labels")));
 
 	add_option (_("Meterbridge"), new BoolOption (
diff --git a/gtk2_ardour/wscript b/gtk2_ardour/wscript
index 3ca9074..9883fa4 100644
--- a/gtk2_ardour/wscript
+++ b/gtk2_ardour/wscript
@@ -370,23 +370,26 @@ def build(bld):
     if bld.is_defined('WINDOWS_VST_SUPPORT'):
         # If we require VST support we build a stub main() and the FST library
         # here using winegcc, and link it to the GTK front-end library
-        obj = bld(features = 'cxx c cxxprogram wine')
-        obj.source = '''
-                ../libs/fst/fst.c
-                ../libs/fst/fstinfofile.c
-                ../libs/fst/vsti.c
-                ../libs/fst/vstwin.c
-                ../vst/winmain.c
-        '''
-        obj.uselib = 'ALSA'
+        obj = bld (features = 'cxx c cxxprogram wine')
+        obj.source = (
+            '../libs/fst/fst.c',
+            '../libs/fst/fstinfofile.c',
+            '../libs/fst/vsti.c',
+            '../libs/fst/vstwin.c',
+            '../vst/winmain.c',
+            )
+        #
+        # XXX do we really need to explicitly link to all of these for the wine executable?
+        #
         obj.use          = [ 'libpbd',
                              'libmidipp',
-                             'libtaglib',
                              'libardour',
                              'libardour_cp',
+                             'libtimecode',
+                             'libmidipp',
                              'libgtk2_ardour',
                              'libgtkmm2ext',
-                             'libtaglib']
+                             ]
         obj.target = 'ardour-' + bld.env['VERSION'] + '-vst.exe.so'
         obj.includes  = [ '../libs/fst', '.' ]
         obj.linkflags = ['-mwindows', '-Wl,--export-dynamic']
@@ -402,28 +405,33 @@ def build(bld):
         obj.target    = 'gtk2_ardour'
     else:
         # just the normal executable version of the GTK GUI
-        obj = bld(features = 'cxx c cxxprogram')
+        obj = bld (features = 'cxx c cxxprogram')
         obj.source    = gtk2_ardour_sources
         obj.target = 'ardour-' + bld.env['VERSION']
         obj.includes = ['.']
 
+    # at this point, "obj" refers to either the normal native executable
+    # OR the shared library built for use with wine on linux.
+
+    obj.use      = [ 'libpbd',
+                     'libardour',
+                     'libardour_cp',
+                     'libtimecode',
+                     'libmidipp',
+                     'libgtkmm2ext',
+                     ]
+
     # continue with setup of obj, which could be a shared library
     # or an executable.
 
     obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3')
-
-    obj.uselib       = 'UUID FLAC FONTCONFIG GLIBMM GTHREAD GTK OGG ALSA CURL DL'
+    obj.uselib       = 'UUID FLAC FONTCONFIG GLIBMM GTHREAD GTK OGG CURL DL'
     obj.uselib       += ' GTKMM GNOMECANVASMM GNOMECANVAS FFTW3F'
     obj.uselib       += ' AUDIOUNITS OSX GTKOSX LO '
-    obj.use          = [ 'libpbd',
-                         'libmidipp',
-                         'ardour',
-                         'libardour_cp',
-                         'libgtkmm2ext']
     if bld.is_defined('USE_EXTERNAL_LIBS'):
         obj.uselib += ' TAGLIB'
     else:
-        obj.use.append('libtaglib')
+        obj.use += ('libtaglib')
     if sys.platform == 'darwin':
         obj.use += ' libappleutility'
     obj.defines     = [
diff --git a/libs/ardour/ardour/audio_backend.h b/libs/ardour/ardour/audio_backend.h
index 26ced33..3874106 100644
--- a/libs/ardour/ardour/audio_backend.h
+++ b/libs/ardour/ardour/audio_backend.h
@@ -282,17 +282,7 @@ class AudioBackend : public PortEngine {
     virtual std::string midi_option () const = 0;
     
     /* State Control */
-
-    /* non-virtual method to avoid possible overrides of default
-     * parameters. See Scott Meyers or other books on C++ to
-     * understand this pattern, or possibly just this:
-     *
-     * http://stackoverflow.com/questions/12139786/good-pratice-default-arguments-for-pure-virtual-method
-     */ 
-    int start (bool for_latency_measurement=false) {
-	    return _start (for_latency_measurement);
-    }
-
+ 
     /** Start using the device named in the most recent call
      * to set_device(), with the parameters set by various
      * the most recent calls to set_sample_rate() etc. etc.
@@ -308,8 +298,24 @@ class AudioBackend : public PortEngine {
      *        any existing systemic latency settings.
      *
      * Return zero if successful, negative values otherwise.
-     */
-    virtual int _start (bool for_latency_measurement) = 0;
+     *
+     *
+     *
+     *
+     * Why is this non-virtual but ::_start() is virtual ?
+     * Virtual methods with default parameters create possible ambiguity
+     * because a derived class may implement the same method with a different
+     * type or value of default parameter.
+     *
+     * So we make this non-virtual method to avoid possible overrides of
+     * default parameters. See Scott Meyers or other books on C++ to understand
+     * this pattern, or possibly just this:
+     *
+     * http://stackoverflow.com/questions/12139786/good-pratice-default-arguments-for-pure-virtual-method
+     */ 
+    int start (bool for_latency_measurement=false) {
+	    return _start (for_latency_measurement);
+    }
 
     /** Stop using the device currently in use. 
      *
@@ -355,7 +361,7 @@ class AudioBackend : public PortEngine {
      * Implementations can feel free to smooth the values returned over
      * time (e.g. high pass filtering, or its equivalent).
      */
-    virtual float cpu_load() const  = 0;
+    virtual float dsp_load() const  = 0;
 
     /* Transport Control (JACK is the only audio API that currently offers
        the concept of shared transport control)
@@ -481,6 +487,8 @@ class AudioBackend : public PortEngine {
 
   protected:
     AudioEngine&          engine;
+
+    virtual int _start (bool for_latency_measurement) = 0;
 };
 
 struct AudioBackendInfo {
diff --git a/libs/ardour/ardour/audio_buffer.h b/libs/ardour/ardour/audio_buffer.h
index 42aba60..054a1f7 100644
--- a/libs/ardour/ardour/audio_buffer.h
+++ b/libs/ardour/ardour/audio_buffer.h
@@ -207,7 +207,7 @@ public:
 		return _data + offset;
 	}
 
-    bool check_silence (pframes_t, pframes_t&) const;
+        bool check_silence (pframes_t, pframes_t&) const;
 
 	void prepare () { _written = false; _silent = false; }
 	bool written() const { return _written; }
diff --git a/libs/ardour/ardour/audioengine.h b/libs/ardour/ardour/audioengine.h
index 7c05f40..09f2ac0 100644
--- a/libs/ardour/ardour/audioengine.h
+++ b/libs/ardour/ardour/audioengine.h
@@ -86,7 +86,7 @@ public:
     int            start (bool for_latency_measurement=false);
     int            stop (bool for_latency_measurement=false);
     int            freewheel (bool start_stop);
-    float          get_cpu_load() const ;
+    float          get_dsp_load() const ;
     void           transport_start ();
     void           transport_stop ();
     TransportState transport_state ();
diff --git a/libs/ardour/ardour/buffer.h b/libs/ardour/ardour/buffer.h
index cbb92e7..4570a7a 100644
--- a/libs/ardour/ardour/buffer.h
+++ b/libs/ardour/ardour/buffer.h
@@ -80,8 +80,8 @@ public:
 	virtual void merge_from (const Buffer& src, framecnt_t len, framecnt_t dst_offset = 0, framecnt_t src_offset = 0) = 0;
 
   protected:
-	Buffer(DataType type, size_t capacity)
-		: _type(type), _capacity(capacity), _size(0), _silent(true)
+	Buffer(DataType type)
+		: _type(type), _capacity(0), _size(0), _silent (true)
 	{}
 
 	DataType  _type;
diff --git a/libs/ardour/ardour/control_protocol_manager.h b/libs/ardour/ardour/control_protocol_manager.h
index 519c762..7d3d487 100644
--- a/libs/ardour/ardour/control_protocol_manager.h
+++ b/libs/ardour/ardour/control_protocol_manager.h
@@ -65,8 +65,8 @@ class ControlProtocolManager : public PBD::Stateful, public ARDOUR::SessionHandl
 	void load_mandatory_protocols ();
 	void midi_connectivity_established ();
 
-	ControlProtocol* instantiate (ControlProtocolInfo&);
-	int              teardown (ControlProtocolInfo&);
+        int activate (ControlProtocolInfo&);
+        int deactivate (ControlProtocolInfo&);
 	
 	std::list<ControlProtocolInfo*> control_protocol_info;
 
@@ -89,6 +89,8 @@ class ControlProtocolManager : public PBD::Stateful, public ARDOUR::SessionHandl
 	int control_protocol_discover (std::string path);
 	ControlProtocolDescriptor* get_descriptor (std::string path);
 	ControlProtocolInfo* cpi_by_name (std::string);
+	ControlProtocol* instantiate (ControlProtocolInfo&);
+	int teardown (ControlProtocolInfo&);
 };
 
 } // namespace
diff --git a/libs/ardour/ardour/session_configuration_vars.h b/libs/ardour/ardour/session_configuration_vars.h
index 5e93c01..6349692 100644
--- a/libs/ardour/ardour/session_configuration_vars.h
+++ b/libs/ardour/ardour/session_configuration_vars.h
@@ -63,5 +63,6 @@ CONFIG_VARIABLE (bool, show_midi_on_meterbridge, "show-midi-on-meterbridge", tru
 CONFIG_VARIABLE (bool, show_rec_on_meterbridge, "show-rec-on-meterbridge", true)
 CONFIG_VARIABLE (bool, show_mute_on_meterbridge, "show-mute-on-meterbridge", false)
 CONFIG_VARIABLE (bool, show_solo_on_meterbridge, "show-solo-on-meterbridge", false)
+CONFIG_VARIABLE (bool, show_monitor_on_meterbridge, "show-monitor-on-meterbridge", false)
 CONFIG_VARIABLE (bool, show_name_on_meterbridge, "show-name-on-meterbridge", true)
 CONFIG_VARIABLE (uint32_t, meterbridge_label_height,  "meterbridge-label-height", 0)
diff --git a/libs/ardour/ardour/slave.h b/libs/ardour/ardour/slave.h
index ca3f618..364929e 100644
--- a/libs/ardour/ardour/slave.h
+++ b/libs/ardour/ardour/slave.h
@@ -183,12 +183,14 @@ class Slave {
 class ISlaveSessionProxy {
   public:
 	virtual ~ISlaveSessionProxy() {}
-	virtual TempoMap&  tempo_map()                 const   { return *((TempoMap *) 0); }
-	virtual framecnt_t frame_rate()                const   { return 0; }
-	virtual framepos_t audible_frame ()            const   { return 0; }
-	virtual framepos_t transport_frame ()          const   { return 0; }
-	virtual pframes_t  frames_since_cycle_start () const   { return 0; }
-	virtual framepos_t frame_time ()               const   { return 0; }
+	virtual TempoMap&  tempo_map()                  const   { return *((TempoMap *) 0); }
+	virtual framecnt_t frame_rate()                 const   { return 0; }
+	virtual pframes_t  frames_per_cycle()           const   { return 0; }
+	virtual framepos_t audible_frame ()             const   { return 0; }
+	virtual framepos_t transport_frame ()           const   { return 0; }
+	virtual pframes_t  frames_since_cycle_start ()  const   { return 0; }
+	virtual pframes_t  sample_time_at_cycle_start() const   { return 0; }
+	virtual framepos_t frame_time ()                const   { return 0; }
 
 	virtual void request_locate (framepos_t /*frame*/, bool with_roll = false) {
 		(void) with_roll;
@@ -204,12 +206,14 @@ class SlaveSessionProxy : public ISlaveSessionProxy {
   public:
 	SlaveSessionProxy(Session &s) : session(s) {}
 
-	TempoMap&  tempo_map()                 const;
-	framecnt_t frame_rate()                const;
-	framepos_t audible_frame ()            const;
-	framepos_t transport_frame ()          const;
-	pframes_t  frames_since_cycle_start () const;
-	framepos_t frame_time ()               const;
+	TempoMap&  tempo_map()                   const;
+	framecnt_t frame_rate()                  const;
+	pframes_t  frames_per_cycle()            const;
+	framepos_t audible_frame ()              const;
+	framepos_t transport_frame ()            const;
+	pframes_t  frames_since_cycle_start ()   const;
+	pframes_t  sample_time_at_cycle_start()  const;
+	framepos_t frame_time ()                 const;
 
 	void request_locate (framepos_t frame, bool with_roll = false);
 	void request_transport_speed (double speed);
diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
index 91b8888..50a9603 100644
--- a/libs/ardour/ardour/types.h
+++ b/libs/ardour/ardour/types.h
@@ -187,7 +187,8 @@ namespace ARDOUR {
 		MeterIEC1NOR   = 0x080,
 		MeterIEC2BBC   = 0x100,
 		MeterIEC2EBU   = 0x200,
-		MeterVU        = 0x400
+		MeterVU        = 0x400,
+		MeterK12       = 0x800
 	};
 
 	enum TrackMode {
diff --git a/libs/ardour/ardour/utils.h b/libs/ardour/ardour/utils.h
index bf91d4d..4bf97fd 100644
--- a/libs/ardour/ardour/utils.h
+++ b/libs/ardour/ardour/utils.h
@@ -57,6 +57,7 @@ static inline float f_max(float x, float a) {
 std::string bump_name_once(const std::string& s, char delimiter);
 
 int cmp_nocase (const std::string& s, const std::string& s2);
+int cmp_nocase_utf8 (const std::string& s1, const std::string& s2);
 
 int touch_file(std::string path);
 
diff --git a/libs/ardour/audio_buffer.cc b/libs/ardour/audio_buffer.cc
index 1fd0337..a36ad81 100644
--- a/libs/ardour/audio_buffer.cc
+++ b/libs/ardour/audio_buffer.cc
@@ -28,15 +28,15 @@ using namespace PBD;
 using namespace ARDOUR;
 
 AudioBuffer::AudioBuffer(size_t capacity)
-	: Buffer(DataType::AUDIO, capacity)
+	: Buffer (DataType::AUDIO)
 	, _owns_data (false)
 	, _data (0)
 {
-	if (_capacity > 0) {
+	if (capacity) {
 		_owns_data = true; // prevent resize() from gagging
-		resize (_capacity);
+		resize (capacity);
 		_silent = false; // force silence on the intial buffer state
-		silence (_capacity);
+		clear ();
 	}
 }
 
@@ -50,21 +50,29 @@ void
 AudioBuffer::resize (size_t size)
 {
 	if (!_owns_data) {
+		/* XXX how the hell is this enforced? */
+		_capacity = size;
 		return;
 	}
 
-	if (size < _capacity) {
-		_size = size;
+	if (_data && size < _capacity) {
+		/* buffer is already large enough */
+		
+		if (size < _size) {
+			/* truncate */
+			_size = size;
+		}
+
 		return;
 	}
 
 	free (_data);
 
+	cache_aligned_malloc ((void**) &_data, sizeof (Sample) * size);
+
 	_capacity = size;
-	_size = size;
+	_size = 0;
 	_silent = false;
-
-	cache_aligned_malloc ((void**) &_data, sizeof (Sample) * _capacity);
 }
 
 bool
diff --git a/libs/ardour/audio_port.cc b/libs/ardour/audio_port.cc
index 6a86360..2fecbf9 100644
--- a/libs/ardour/audio_port.cc
+++ b/libs/ardour/audio_port.cc
@@ -56,14 +56,11 @@ AudioPort::cycle_start (pframes_t nframes)
 }
 
 void
-AudioPort::cycle_end (pframes_t)
+AudioPort::cycle_end (pframes_t nframes)
 {
         if (sends_output() && !_buffer->written()) {
-                /* we can't use nframes here because the current buffer capacity may
-                   be shorter than the full buffer size if we split the cycle.
-                */
-		if (_buffer->capacity () > 0) {
-			_buffer->silence (_buffer->capacity());
+		if (_buffer->capacity() >= nframes) {
+			_buffer->silence (nframes);
 		}
 	}
 }
diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
index 7f4d3c2..82564eb 100644
--- a/libs/ardour/audioengine.cc
+++ b/libs/ardour/audioengine.cc
@@ -675,12 +675,12 @@ AudioEngine::freewheel (bool start_stop)
 }
 
 float
-AudioEngine::get_cpu_load() const 
+AudioEngine::get_dsp_load() const 
 {
 	if (!_backend) {
 		return 0.0;
 	}
-	return _backend->cpu_load ();
+	return _backend->dsp_load ();
 }
 
 bool
diff --git a/libs/ardour/buffer_set.cc b/libs/ardour/buffer_set.cc
index e67aee6..227d7a1 100644
--- a/libs/ardour/buffer_set.cc
+++ b/libs/ardour/buffer_set.cc
@@ -167,7 +167,7 @@ BufferSet::ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capac
 	// If there's not enough or they're too small, just nuke the whole thing and
 	// rebuild it (so I'm lazy..)
 	if (bufs.size() < num_buffers
-			|| (bufs.size() > 0 && bufs[0]->capacity() < buffer_capacity)) {
+	    || (bufs.size() > 0 && bufs[0]->capacity() < buffer_capacity)) {
 
 		// Nuke it
 		for (BufferVec::iterator i = bufs.begin(); i != bufs.end(); ++i) {
@@ -179,7 +179,7 @@ BufferSet::ensure_buffers(DataType type, size_t num_buffers, size_t buffer_capac
 		for (size_t i = 0; i < num_buffers; ++i) {
 			bufs.push_back(Buffer::create(type, buffer_capacity));
 		}
-
+		
 		_available.set(type, num_buffers);
 		_count.set (type, num_buffers);
 	}
diff --git a/libs/ardour/control_protocol_manager.cc b/libs/ardour/control_protocol_manager.cc
index 2e65a8d..974258a 100644
--- a/libs/ardour/control_protocol_manager.cc
+++ b/libs/ardour/control_protocol_manager.cc
@@ -72,26 +72,54 @@ ControlProtocolManager::set_session (Session* s)
 
 		for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
 			if ((*i)->requested || (*i)->mandatory) {
-				
-				instantiate (**i);
-				(*i)->requested = false;
-
-				if ((*i)->protocol) {
-					if ((*i)->state) {
-						(*i)->protocol->set_state (*(*i)->state, Stateful::loading_state_version);
-					} else {
-						/* guarantee a call to
-						   set_state() whether we have
-						   existing state or not
-						*/
-						(*i)->protocol->set_state (XMLNode(""), Stateful::loading_state_version);
-					}
-				}
+				(void) activate (**i);
 			}
 		}
 	}
 }
 
+int
+ControlProtocolManager::activate (ControlProtocolInfo& cpi)
+{
+	ControlProtocol* cp;
+
+	cpi.requested = true;
+
+	if ((cp = instantiate (cpi)) == 0) {
+		return -1;
+	}
+
+	/* we split the set_state() and set_active() operations so that
+	   protocols that need state to configure themselves (e.g. "What device
+	   is connected, or supposed to be connected?") can get it before
+	   actually starting any interaction.
+	*/
+
+	if (cpi.state) {
+		/* force this by tweaking the internals of the state
+		 * XMLNode. Ugh.
+		 */
+		cp->set_state (*cpi.state, Stateful::loading_state_version);
+	} else {
+		/* guarantee a call to
+		   set_state() whether we have
+		   existing state or not
+		*/
+		cp->set_state (XMLNode(""), Stateful::loading_state_version);
+	}
+
+	cp->set_active (true);
+
+	return 0;
+}	
+
+int
+ControlProtocolManager::deactivate (ControlProtocolInfo& cpi)
+{
+	cpi.requested = false;
+	return teardown (cpi);
+}
+
 void
 ControlProtocolManager::session_going_away()
 {
@@ -163,6 +191,12 @@ ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
 	if (cpi.mandatory) {
 		return 0;
 	}
+	
+	/* save current state */
+
+	delete cpi.state;
+	cpi.state = new XMLNode (cpi.protocol->get_state());
+	cpi.state->add_property (X_("active"), "no");
 
 	cpi.descriptor->destroy (cpi.descriptor, cpi.protocol);
 
@@ -177,8 +211,6 @@ ControlProtocolManager::teardown (ControlProtocolInfo& cpi)
 	}
 
 	cpi.protocol = 0;
-	delete cpi.state;
-	cpi.state = 0;
 	dlclose (cpi.descriptor->module);
 
 	ProtocolStatusChange (&cpi);
@@ -379,22 +411,21 @@ ControlProtocolManager::get_state ()
 
 	for (list<ControlProtocolInfo*>::iterator i = control_protocol_info.begin(); i != control_protocol_info.end(); ++i) {
 
-		XMLNode * child;
-
 		if ((*i)->protocol) {
-			child = &((*i)->protocol->get_state());
-			child->add_property (X_("active"), "yes");
-			// should we update (*i)->state here?  probably.
-			root->add_child_nocopy (*child);
+			XMLNode& child_state ((*i)->protocol->get_state());
+			child_state.add_property (X_("active"), "yes");
+			root->add_child_nocopy (child_state);
 		} else if ((*i)->state) {
-			// keep ownership clear
-			root->add_child_copy (*(*i)->state);
+			XMLNode* child_state = new XMLNode (*(*i)->state);
+			child_state->add_property (X_("active"), "no");
+			root->add_child_nocopy (*child_state);
 		} else {
-			child = new XMLNode (X_("Protocol"));
-			child->add_property (X_("name"), (*i)->name);
-			child->add_property (X_("active"), "no");
-			root->add_child_nocopy (*child);
+			XMLNode* child_state = new XMLNode (X_("Protocol"));
+			child_state->add_property (X_("name"), (*i)->name);
+			child_state->add_property (X_("active"), "no");
+			root->add_child_nocopy (*child_state);
 		}
+
 	}
 
 	return *root;
diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
index 72125f8..e32fe32 100644
--- a/libs/ardour/enums.cc
+++ b/libs/ardour/enums.cc
@@ -179,6 +179,7 @@ setup_enum_writer ()
 	REGISTER_ENUM (MeterKrms);
 	REGISTER_ENUM (MeterK20);
 	REGISTER_ENUM (MeterK14);
+	REGISTER_ENUM (MeterK12);
 	REGISTER_ENUM (MeterIEC1DIN);
 	REGISTER_ENUM (MeterIEC1NOR);
 	REGISTER_ENUM (MeterIEC2BBC);
diff --git a/libs/ardour/export_channel.cc b/libs/ardour/export_channel.cc
index 82e5d80..c67f33b 100644
--- a/libs/ardour/export_channel.cc
+++ b/libs/ardour/export_channel.cc
@@ -131,7 +131,7 @@ RegionExportChannelFactory::RegionExportChannelFactory (Session * session, Audio
 
 		mixdown_buffer.reset (new Sample [frames_per_cycle]);
 		gain_buffer.reset (new Sample [frames_per_cycle]);
-		memset (gain_buffer.get(), 1.0, sizeof (Sample) * frames_per_cycle);
+		std::fill_n (gain_buffer.get(), frames_per_cycle, Sample (1.0));
 
 		break;
 	  case Processed:
diff --git a/libs/ardour/linux_vst_support.cc b/libs/ardour/linux_vst_support.cc
index 1fccf79..9d36905 100644
--- a/libs/ardour/linux_vst_support.cc
+++ b/libs/ardour/linux_vst_support.cc
@@ -242,7 +242,15 @@ vstfx_load (const char *path)
 
 	/*Find the main entry point into the plugin*/
 
-	if ((fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "main")) == 0)
+	fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "main");
+
+	if (fhandle->main_entry == 0) {
+		if ((fhandle->main_entry = (main_entry_t) dlsym(fhandle->dll, "VSTPluginMain")) != 0) {
+			PBD::warning << path << _(": is a VST >= 2.4 - this plugin may or may not function correctly with this version of Ardour.") << endmsg;
+		}
+	}
+
+	if (fhandle->main_entry == 0)
 	{
 		/*If it can't be found, unload the plugin and return a 0 handle*/
 		
diff --git a/libs/ardour/lv2_plugin.cc b/libs/ardour/lv2_plugin.cc
index f5dcc26..a1d9de1 100644
--- a/libs/ardour/lv2_plugin.cc
+++ b/libs/ardour/lv2_plugin.cc
@@ -1162,10 +1162,14 @@ LV2Plugin::write_from_ui(uint32_t       index,
 		 *  e.g 48kSPS / 128fpp -> audio-periods = 375 Hz
 		 *  ui-periods = 25 Hz (SuperRapidScreenUpdate)
 		 *  default minimumSize = 32K (see LV2Plugin::allocate_atom_event_buffers()
-		 *  -> 15 * 32K
-		 * it is safe to overflow (but the plugin state may be inconsistent).
+		 *
+		 * it is NOT safe to overflow (msg.size will be misinterpreted)
 		 */
-		rbs = max((size_t) 32768 * 6, rbs);
+		uint32_t bufsiz = 32768;
+		if (_atom_ev_buffers && _atom_ev_buffers[0]) {
+			bufsiz =  lv2_evbuf_get_capacity(_atom_ev_buffers[0]);
+		}
+		rbs = max((size_t) bufsiz * 8, rbs);
 		_from_ui = new RingBuffer<uint8_t>(rbs);
 	}
 
@@ -1194,8 +1198,12 @@ LV2Plugin::enable_ui_emmission()
 {
 	if (!_to_ui) {
 		/* see note in LV2Plugin::write_from_ui() */
+		uint32_t bufsiz = 32768;
+		if (_atom_ev_buffers && _atom_ev_buffers[0]) {
+			bufsiz =  lv2_evbuf_get_capacity(_atom_ev_buffers[0]);
+		}
 		size_t rbs = _session.engine().raw_buffer_size(DataType::MIDI) * NBUFS;
-		rbs = max((size_t) 32768 * 8, rbs);
+		rbs = max((size_t) bufsiz * 8, rbs);
 		_to_ui = new RingBuffer<uint8_t>(rbs);
 	}
 }
@@ -1508,7 +1516,7 @@ LV2Plugin::allocate_atom_event_buffers()
 		return;
 	}
 
-	DEBUG_TRACE(DEBUG::LV2, string_compose("allocate %1 atom_ev_buffers\n", total_atom_buffers));
+	DEBUG_TRACE(DEBUG::LV2, string_compose("allocate %1 atom_ev_buffers of %d bytes\n", total_atom_buffers, minimumSize));
 	_atom_ev_buffers = (LV2_Evbuf**) malloc((total_atom_buffers + 1) * sizeof(LV2_Evbuf*));
 	for (int i = 0; i < total_atom_buffers; ++i ) {
 		_atom_ev_buffers[i] = lv2_evbuf_new(minimumSize, LV2_EVBUF_ATOM,
@@ -1681,6 +1689,9 @@ LV2Plugin::connect_and_run(BufferSet& bufs,
 				}
 			} else if (!valid) {
 				// Nothing we understand or care about, connect to scratch
+				// see note for midi-buffer size above
+				scratch_bufs.ensure_lv2_bufsize((flags & PORT_INPUT),
+						0, _port_minimumSize[port_index]);
 				_ev_buffers[port_index] = scratch_bufs.get_lv2_midi(
 					(flags & PORT_INPUT), 0, (flags & PORT_EVENT));
 			}
diff --git a/libs/ardour/meter.cc b/libs/ardour/meter.cc
index a7857f5..5310fd7 100644
--- a/libs/ardour/meter.cc
+++ b/libs/ardour/meter.cc
@@ -108,7 +108,7 @@ PeakMeter::run (BufferSet& bufs, framepos_t /*start_frame*/, framepos_t /*end_fr
 	// Meter audio in to the rest of the peaks
 	for (uint32_t i = 0; i < n_audio; ++i, ++n) {
 		_peak_signal[n] = compute_peak (bufs.get_audio(i).data(), nframes, _peak_signal[n]);
-		if (_meter_type & (MeterKrms | MeterK20 | MeterK14)) {
+		if (_meter_type & (MeterKrms | MeterK20 | MeterK14 | MeterK12)) {
 			_kmeter[i]->process(bufs.get_audio(i).data(), nframes);
 		}
 		if (_meter_type & (MeterIEC1DIN | MeterIEC1NOR)) {
@@ -288,7 +288,7 @@ PeakMeter::meter ()
 	/* 0.01f ^= 100 Hz update rate */
 	const float midi_meter_falloff = Config->get_meter_falloff() * 0.01f;
 	/* kmeters: 24dB / 2 sec */
-	const float audio_meter_falloff = (_meter_type & (MeterK20 | MeterK14)) ? 0.12f : midi_meter_falloff;
+	const float audio_meter_falloff = (_meter_type & (MeterK20 | MeterK14 | MeterK12)) ? 0.12f : midi_meter_falloff;
 
 	for (size_t n = 0; n < limit; ++n) {
 
@@ -345,6 +345,7 @@ PeakMeter::meter_level(uint32_t n, MeterType type) {
 		case MeterKrms:
 		case MeterK20:
 		case MeterK14:
+		case MeterK12:
 			{
 				const uint32_t n_midi = current_meters.n_midi();
 				if (CHECKSIZE(_kmeter)) {
@@ -404,7 +405,7 @@ PeakMeter::set_type(MeterType t)
 
 	_meter_type = t;
 
-	if (t & (MeterKrms | MeterK20 | MeterK14)) {
+	if (t & (MeterKrms | MeterK20 | MeterK14 | MeterK12)) {
 		const size_t n_audio = current_meters.n_audio();
 		for (size_t n = 0; n < n_audio; ++n) {
 			_kmeter[n]->reset();
diff --git a/libs/ardour/midi_buffer.cc b/libs/ardour/midi_buffer.cc
index d75b861..1a6cb7f 100644
--- a/libs/ardour/midi_buffer.cc
+++ b/libs/ardour/midi_buffer.cc
@@ -33,12 +33,12 @@ using namespace PBD;
 
 // FIXME: mirroring for MIDI buffers?
 MidiBuffer::MidiBuffer(size_t capacity)
-	: Buffer(DataType::MIDI, capacity)
-	, _data(0)
+	: Buffer (DataType::MIDI)
+	, _data (0)
 {
 	if (capacity) {
-		resize(_capacity);
-		silence(_capacity);
+		resize (capacity);
+		silence (capacity);
 	}
 }
 
@@ -50,17 +50,22 @@ MidiBuffer::~MidiBuffer()
 void
 MidiBuffer::resize(size_t size)
 {
-	assert(size > 0);
+	if (_data && size < _capacity) {
+
+		if (_size < size) {
+			/* truncate */
+			_size = size;
+		}
 
-	if (size < _capacity) {
 		return;
 	}
 
-	free(_data);
+	free (_data);
+
+	cache_aligned_malloc ((void**) &_data, size);
 
 	_size = 0;
 	_capacity = size;
-	cache_aligned_malloc ((void**) &_data, _capacity);
 
 	assert(_data);
 }
diff --git a/libs/ardour/midi_clock_slave.cc b/libs/ardour/midi_clock_slave.cc
index 7eaeeb9..762d944 100644
--- a/libs/ardour/midi_clock_slave.cc
+++ b/libs/ardour/midi_clock_slave.cc
@@ -45,7 +45,7 @@ using namespace PBD;
 
 MIDIClock_Slave::MIDIClock_Slave (Session& s, MidiPort& p, int ppqn)
 	: ppqn (ppqn)
-	, bandwidth (10.0 / 60.0) // 1 BpM = 1 / 60 Hz
+	, bandwidth (2.0 / 60.0) // 1 BpM = 1 / 60 Hz
 {
 	session = (ISlaveSessionProxy *) new SlaveSessionProxy(s);
 	rebind (p);
@@ -55,7 +55,7 @@ MIDIClock_Slave::MIDIClock_Slave (Session& s, MidiPort& p, int ppqn)
 MIDIClock_Slave::MIDIClock_Slave (ISlaveSessionProxy* session_proxy, int ppqn)
 	: session(session_proxy)
 	, ppqn (ppqn)
-	, bandwidth (10.0 / 60.0) // 1 BpM = 1 / 60 Hz
+	, bandwidth (2.0 / 60.0) // 1 BpM = 1 / 60 Hz
 {
 	reset ();
 }
@@ -123,6 +123,8 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, framepos_t timestamp)
 		return;
 	}
 
+	pframes_t cycle_offset = timestamp - session->sample_time_at_cycle_start();
+
 	calculate_one_ppqn_in_frames_at(should_be_position);
 
 	framepos_t elapsed_since_start = timestamp - first_timestamp;
@@ -134,6 +136,8 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, framepos_t timestamp)
 		first_timestamp = timestamp;
 		elapsed_since_start = should_be_position;
 
+		DEBUG_TRACE (DEBUG::MidiClock, string_compose ("first clock message after start received @ %1\n", timestamp));
+
 		// calculate filter coefficients
 		calculate_filter_coefficients();
 
@@ -153,7 +157,7 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, framepos_t timestamp)
 		// we use session->transport_frame() instead of t1 here
 		// because t1 is used to calculate the transport speed,
 		// so the loop will compensate for accumulating rounding errors
-		error = (double(should_be_position) - double(session->transport_frame()));
+		error = (double(should_be_position) - (double(session->transport_frame()) + double(cycle_offset)));
 		e = error / double(session->frame_rate());
 		current_delta = error;
 
@@ -163,21 +167,23 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, framepos_t timestamp)
 		e2 += c * e;
 	}
 
-	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("clock #%1 @ %2 arrived %3 (theoretical) audible %4 transport %5 error %6 "
-						       "read delta %7 should-be delta %8 t1-t0 %9 t0 %10 t1 %11 framerate %12 appspeed %13\n",
-						       midi_clock_count,
-						       elapsed_since_start,
-						       should_be_position,
-						       session->audible_frame(),
-						       session->transport_frame(),
-						       error,
-						       timestamp - last_timestamp,
-						       one_ppqn_in_frames,
-						       (t1 -t0) * session->frame_rate(),
-						       t0 * session->frame_rate(),
-						       t1 * session->frame_rate(),
-						       session->frame_rate(),
-						       ((t1 - t0) * session->frame_rate()) / one_ppqn_in_frames));
+	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("clock #%1 @ %2 should-be %3 transport %4 error %5 appspeed %6 "
+						       "read-delta %7 should-be delta %8 t1-t0 %9 t0 %10 t1 %11 framerate %12 engine %13\n",
+						       midi_clock_count,                                          // #
+						       elapsed_since_start,                                       // @
+						       should_be_position,                                        // should-be
+						       session->transport_frame(),                                // transport
+						       error,                                                     // error
+						       ((t1 - t0) * session->frame_rate()) / one_ppqn_in_frames, // appspeed
+						       timestamp - last_timestamp,                                // read delta
+						       one_ppqn_in_frames,                                        // should-be delta
+						       (t1 - t0) * session->frame_rate(),                         // t1-t0
+						       t0 * session->frame_rate(),                                // t0
+						       t1 * session->frame_rate(),                                // t1
+						       session->frame_rate(),                                      // framerate
+						       session->frame_time()
+
+	));
 
 	last_timestamp = timestamp;
 }
@@ -185,7 +191,7 @@ MIDIClock_Slave::update_midi_clock (Parser& /*parser*/, framepos_t timestamp)
 void
 MIDIClock_Slave::start (Parser& /*parser*/, framepos_t timestamp)
 {
-	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MIDIClock_Slave got start message at time %1 engine time %2\n", timestamp, session->frame_time()));
+	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MIDIClock_Slave got start message at time %1 engine time %2 transport_frame %3\n", timestamp, session->frame_time(), session->transport_frame()));
 
 	if (!_started) {
 		reset();
@@ -200,6 +206,8 @@ MIDIClock_Slave::start (Parser& /*parser*/, framepos_t timestamp)
 void
 MIDIClock_Slave::reset ()
 {
+	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("MidiClock_Slave reset(): calculated filter bandwidth is %1 for period size %2\n", bandwidth, session->frames_per_cycle()));
+
 	should_be_position = session->transport_frame();
 	last_timestamp = 0;
 
@@ -345,7 +353,7 @@ MIDIClock_Slave::speed_and_position (double& speed, framepos_t& pos)
 		pos = should_be_position;
 	}
 
-	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("speed_and_position: %1 & %2 <-> %3 (transport)\n", speed, pos, session->transport_frame()));
+	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("speed_and_position: speed %1 should-be %2 transport %3 \n", speed, pos, session->transport_frame()));
 
 	return true;
 }
diff --git a/libs/ardour/midi_ui.cc b/libs/ardour/midi_ui.cc
index 0729132..b80370e 100644
--- a/libs/ardour/midi_ui.cc
+++ b/libs/ardour/midi_ui.cc
@@ -61,6 +61,8 @@ MidiControlUI::do_request (MidiUIRequest* req)
 {
 	if (req->type == Quit) {
 		BaseUI::quit ();
+	} else if (req->type == CallSlot) {
+		req->the_slot ();
 	}
 }
 
diff --git a/libs/ardour/processor.cc b/libs/ardour/processor.cc
index f9590be..d571f55 100644
--- a/libs/ardour/processor.cc
+++ b/libs/ardour/processor.cc
@@ -63,6 +63,7 @@ Processor::Processor(Session& session, const string& name)
 	, _display_to_user (true)
 	, _pre_fader (false)
 	, _ui_pointer (0)
+	, _owner (0)
 {
 }
 
diff --git a/libs/ardour/session_process.cc b/libs/ardour/session_process.cc
index 3c46a2e..18dfbf2 100644
--- a/libs/ardour/session_process.cc
+++ b/libs/ardour/session_process.cc
@@ -83,7 +83,7 @@ Session::process (pframes_t nframes)
 	 */
 
 	try {
-		if (!_engine.freewheeling() && Config->get_send_midi_clock() && transport_speed() == 1.0f && midi_clock->has_midi_port()) {
+		if (!_silent && !_engine.freewheeling() && Config->get_send_midi_clock() && (transport_speed() == 1.0f || transport_speed() == 0.0f) && midi_clock->has_midi_port()) {
 			midi_clock->tick (transport_at_start, nframes);
 		}
 	} catch (...) {
diff --git a/libs/ardour/slave.cc b/libs/ardour/slave.cc
index e8c63b4..c0678ce 100644
--- a/libs/ardour/slave.cc
+++ b/libs/ardour/slave.cc
@@ -35,6 +35,12 @@ SlaveSessionProxy::frame_rate() const
 	return session.frame_rate();
 }
 
+pframes_t
+SlaveSessionProxy::frames_per_cycle() const
+{
+	return session.engine().samples_per_cycle();
+}
+
 framepos_t
 SlaveSessionProxy::audible_frame() const
 {
@@ -53,6 +59,13 @@ SlaveSessionProxy::frames_since_cycle_start() const
 	return session.engine().samples_since_cycle_start();
 }
 
+pframes_t
+SlaveSessionProxy::sample_time_at_cycle_start() const
+{
+	return session.engine().sample_time_at_cycle_start();
+}
+
+
 framepos_t
 SlaveSessionProxy::frame_time() const
 {
diff --git a/libs/ardour/test/interpolation_test.cc b/libs/ardour/test/interpolation_test.cc
index 23789f8..e8ed22d 100644
--- a/libs/ardour/test/interpolation_test.cc
+++ b/libs/ardour/test/interpolation_test.cc
@@ -106,6 +106,7 @@ InterpolationTest::cubicInterpolationTest ()
 	cubic.set_speed (1.0);
 	cubic.set_target_speed (cubic.speed());
 	result = cubic.interpolate (0, NUM_SAMPLES, input, output);
+	CPPUNIT_ASSERT_EQUAL (result, cubic.interpolate (0, NUM_SAMPLES, NULL, NULL));
 	CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES * cubic.speed()), result);
 	for (int i = 0; i < NUM_SAMPLES; i += INTERVAL) {
 		CPPUNIT_ASSERT_EQUAL (1.0f, output[i]);
@@ -116,6 +117,7 @@ InterpolationTest::cubicInterpolationTest ()
 	cubic.set_speed (0.5);
 	cubic.set_target_speed (cubic.speed());
 	result = cubic.interpolate (0, NUM_SAMPLES, input, output);
+	CPPUNIT_ASSERT_EQUAL (result, cubic.interpolate (0, NUM_SAMPLES, NULL, NULL));
 	CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES * cubic.speed()), result);
 	for (int i = 0; i < NUM_SAMPLES; i += (INTERVAL / cubic.speed() +0.5)) {
 		CPPUNIT_ASSERT_EQUAL (1.0f, output[i]);
@@ -126,6 +128,7 @@ InterpolationTest::cubicInterpolationTest ()
 	cubic.set_speed (0.2);
 	cubic.set_target_speed (cubic.speed());
 	result = cubic.interpolate (0, NUM_SAMPLES, input, output);
+	CPPUNIT_ASSERT_EQUAL (result, cubic.interpolate (0, NUM_SAMPLES, NULL, NULL));
 	CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES * cubic.speed()), result);
 
 //	cout << "\nSpeed: 0.02";
@@ -133,6 +136,7 @@ InterpolationTest::cubicInterpolationTest ()
 	cubic.set_speed (0.02);
 	cubic.set_target_speed (cubic.speed());
 	result = cubic.interpolate (0, NUM_SAMPLES, input, output);
+	CPPUNIT_ASSERT_EQUAL (result, cubic.interpolate (0, NUM_SAMPLES, NULL, NULL));
 	CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES * cubic.speed()), result);
 
 	/* This one fails due too error accumulation
@@ -150,6 +154,7 @@ InterpolationTest::cubicInterpolationTest ()
 	cubic.set_speed (2.0);
 	cubic.set_target_speed (cubic.speed());
 	result = cubic.interpolate (0, NUM_SAMPLES / 2, input, output);
+	CPPUNIT_ASSERT_EQUAL (result, cubic.interpolate (0, NUM_SAMPLES / 2, NULL, NULL));
 	CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES / 2 * cubic.speed()), result);
 	for (int i = 0; i < NUM_SAMPLES / 2; i += (INTERVAL / cubic.speed() +0.5)) {
 		CPPUNIT_ASSERT_EQUAL (1.0f, output[i]);
@@ -159,6 +164,7 @@ InterpolationTest::cubicInterpolationTest ()
 	cubic.set_speed (10.0);
 	cubic.set_target_speed (cubic.speed());
 	result = cubic.interpolate (0, NUM_SAMPLES / 10, input, output);
+	CPPUNIT_ASSERT_EQUAL (result, cubic.interpolate (0, NUM_SAMPLES / 10, NULL, NULL));
 	CPPUNIT_ASSERT_EQUAL ((framecnt_t)(NUM_SAMPLES / 10 * cubic.speed()), result);
 	for (int i = 0; i < NUM_SAMPLES / 10; i += (INTERVAL / cubic.speed() +0.5)) {
 		CPPUNIT_ASSERT_EQUAL (1.0f, output[i]);
diff --git a/libs/ardour/thread_buffers.cc b/libs/ardour/thread_buffers.cc
index fd3160b..e469187 100644
--- a/libs/ardour/thread_buffers.cc
+++ b/libs/ardour/thread_buffers.cc
@@ -60,7 +60,7 @@ ThreadBuffers::ensure_buffers (ChanCount howmany)
 
 	for (DataType::iterator t = DataType::begin(); t != DataType::end(); ++t) {
 		size_t count = std::max (scratch_buffers->available().get(*t), howmany.get(*t));
-		size_t size = _engine->raw_buffer_size (*t);
+		size_t size = _engine->raw_buffer_size (*t) / sizeof (Sample);
 
 		scratch_buffers->ensure_buffers (*t, count, size);
 		mix_buffers->ensure_buffers (*t, count, size);
@@ -68,12 +68,14 @@ ThreadBuffers::ensure_buffers (ChanCount howmany)
 		route_buffers->ensure_buffers (*t, count, size);
 	}
 
+	size_t audio_buffer_size = _engine->raw_buffer_size (DataType::AUDIO) / sizeof (Sample);
+
 	delete [] gain_automation_buffer;
-	gain_automation_buffer = new gain_t[_engine->raw_buffer_size (DataType::AUDIO)];
+	gain_automation_buffer = new gain_t[audio_buffer_size];
 	delete [] send_gain_automation_buffer;
-	send_gain_automation_buffer = new gain_t[_engine->raw_buffer_size (DataType::AUDIO)];
+	send_gain_automation_buffer = new gain_t[audio_buffer_size];
 
-	allocate_pan_automation_buffers (_engine->raw_buffer_size (DataType::AUDIO), howmany.n_audio(), false);
+	allocate_pan_automation_buffers (audio_buffer_size, howmany.n_audio(), false);
 }
 
 void
diff --git a/libs/ardour/ticker.cc b/libs/ardour/ticker.cc
index 9a29df2..9a2cff7 100644
--- a/libs/ardour/ticker.cc
+++ b/libs/ardour/ticker.cc
@@ -38,58 +38,66 @@ class MidiClockTicker::Position : public Timecode::BBT_Time
 {
 public:
 
-	Position() : speed(0.0f), frame(0) { }
-	~Position() { }
-
-	/** Sync timing information taken from the given Session
-		@return True if timings differed */
-	bool sync (Session* s) {
-
-		bool didit = false;
-
-		double     sp = s->transport_speed();
-		framecnt_t fr = s->transport_frame();
-
-		if (speed != sp) {
-			speed = sp;
-			didit = true;
-		}
-
-		if (frame != fr) {
-			frame = fr;
-			didit = true;
-		}
-
-		/* Midi beats and clocks always gets updated for now */
-
-		s->bbt_time (this->frame, *this);
-
-		const TempoMap& tempo = s->tempo_map();
-
-		const double divisions   = tempo.meter_at(frame).divisions_per_bar();
-		const double divisor     = tempo.meter_at(frame).note_divisor();
-		const double qnote_scale = divisor * 0.25f;
-
-		/** Midi Beats in terms of Song Position Pointer is equivalent to total
-			sixteenth notes at 'time' */
-
-		midi_beats  = (((bars - 1) * divisions) + beats - 1);
-		midi_beats += (double)ticks / (double)Position::ticks_per_beat * qnote_scale;
-		midi_beats *= 16.0f / divisor;
-
-		midi_clocks = midi_beats * 6.0f;
-
-		return didit;
-	}
-
-	double      speed;
-	framecnt_t  frame;
-	double      midi_beats;
-	double      midi_clocks;
-
-	void print (std::ostream& s) {
-		s << "frames: " << frame << " midi beats: " << midi_beats << " speed: " << speed;
-	}
+    Position() : speed(0.0f), frame(0) { }
+    ~Position() { }
+    
+    /** Sync timing information taken from the given Session
+     * @return True if timings differed 
+     */
+
+    bool sync (Session* s) {
+
+	    bool changed = false;
+	    
+	    double     sp = s->transport_speed();
+	    framecnt_t fr = s->transport_frame();
+	    
+	    if (speed != sp) {
+		    speed = sp;
+		    changed = true;
+	    }
+
+	    if (frame != fr) {
+		    frame = fr;
+		    changed = true;
+	    }
+
+	    /* Midi beats and clocks always gets updated for now */
+
+	    s->bbt_time (this->frame, *this);
+
+	    const TempoMap& tempo = s->tempo_map();
+
+	    const double divisions   = tempo.meter_at(frame).divisions_per_bar();
+	    const double divisor     = tempo.meter_at(frame).note_divisor();
+	    const double qnote_scale = divisor * 0.25f;
+	    double mb;
+
+	    /** Midi Beats in terms of Song Position Pointer is equivalent to total
+	     * sixteenth notes at 'time' 
+	     */
+
+	    mb  = (((bars - 1) * divisions) + beats - 1);
+	    mb += (double)ticks / (double)Position::ticks_per_beat * qnote_scale;
+	    mb *= 16.0f / divisor;
+
+	    if (mb != midi_beats) {
+		    midi_beats = mb;
+		    midi_clocks = midi_beats * 6.0f;
+		    changed = true;
+	    }
+
+	    return changed;
+    }
+
+    double      speed;
+    framecnt_t  frame;
+    double      midi_beats;
+    double      midi_clocks;
+    
+    void print (std::ostream& s) {
+	    s << "frames: " << frame << " midi beats: " << midi_beats << " speed: " << speed;
+    }
 };
 
 
@@ -127,7 +135,7 @@ MidiClockTicker::session_located()
 {
 	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Session Located: %1, speed: %2\n", _session->transport_frame(), _session->transport_speed()));
 
-	if (0 == _session || ! _pos->sync (_session)) {
+	if (!_session || !_pos->sync (_session)) {
 		return;
 	}
 
@@ -212,37 +220,30 @@ MidiClockTicker::transport_looped()
 void
 MidiClockTicker::tick (const framepos_t& /* transport_frame */, pframes_t nframes)
 {
-	if (!Config->get_send_midi_clock() || _session == 0 || _session->transport_speed() != 1.0f || _midi_port == 0) {
+	if (!Config->get_send_midi_clock() || _session == 0 || _midi_port == 0) {
 		return;
 	}
 
 	if (_send_pos) {
 		if (_pos->speed == 0.0f) {
-			uint32_t where = llrint (_pos->midi_beats);
-			send_position_event (where, 0, nframes);
+			send_position_event (llrint (_pos->midi_beats), 0, nframes);
 		} else if (_pos->speed == 1.0f) {
-#if 1
-			/* Experimental.  To really do this and have accuracy, the
-			   stop/locate/continue sequence would need queued to send immediately
-			   before the next midi clock. */
-			
 			send_stop_event (0, nframes);
 			
 			if (_pos->frame == 0) {
 				send_start_event (0, nframes);
 			} else {
-				uint32_t where = llrint (_pos->midi_beats);
-				send_position_event (where, 0, nframes);
+				send_position_event (llrint (_pos->midi_beats), 0, nframes);
 				send_continue_event (0, nframes);
 			}
-#endif
 		} else {
 			/* Varispeed not supported */
 		}
 
-		_send_pos = true;
+		_send_pos = false;
 	}
 
+
 	if (_send_state) {
 		if (_pos->speed == 1.0f) {
 			if (_session->get_play_loop()) {
@@ -270,6 +271,10 @@ MidiClockTicker::tick (const framepos_t& /* transport_frame */, pframes_t nframe
 		_send_state = false;
 	}
 
+	if (_session->transport_speed() != 1.0f) {
+		/* no varispeed support and nothing to do after this if stopped */
+		return;
+	}
 
 	const framepos_t end = _pos->frame + nframes;
 	double iter = _last_tick;
@@ -317,11 +322,12 @@ MidiClockTicker::send_midi_clock_event (pframes_t offset, pframes_t nframes)
 		return;
 	}
 
-	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Tick with offset %1\n", offset));
+	static uint8_t msg = MIDI_CMD_COMMON_CLOCK;
 
-	static uint8_t tick_byte = { MIDI_CMD_COMMON_CLOCK };
 	MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
-	mb.push_back (offset, 1, &tick_byte);
+	mb.push_back (offset, 1, &msg);
+
+	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Tick with offset %1\n", offset));
 }
 
 void
@@ -331,11 +337,11 @@ MidiClockTicker::send_start_event (pframes_t offset, pframes_t nframes)
 		return;
 	}
 
-	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Start %1\n", _last_tick));
-
-	static uint8_t tick_byte = { MIDI_CMD_COMMON_START };
+	static uint8_t msg = { MIDI_CMD_COMMON_START };
 	MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
-	mb.push_back (offset, 1, &tick_byte);
+	mb.push_back (offset, 1, &msg);
+
+	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Start %1\n", _last_tick));
 }
 
 void
@@ -345,11 +351,11 @@ MidiClockTicker::send_continue_event (pframes_t offset, pframes_t nframes)
 		return;
 	}
 
-	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Continue %1\n", _last_tick));
-
-	static uint8_t tick_byte = { MIDI_CMD_COMMON_CONTINUE };
+	static uint8_t msg = { MIDI_CMD_COMMON_CONTINUE };
 	MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
-	mb.push_back (offset, 1, &tick_byte);
+	mb.push_back (offset, 1, &msg);
+
+	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Continue %1\n", _last_tick));
 }
 
 void
@@ -359,11 +365,11 @@ MidiClockTicker::send_stop_event (pframes_t offset, pframes_t nframes)
 		return;
 	}
 
-	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Stop %1\n", _last_tick));
-
-	static uint8_t tick_byte = { MIDI_CMD_COMMON_STOP };
+	static uint8_t msg = MIDI_CMD_COMMON_STOP;
 	MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
-	mb.push_back (offset, 1, &tick_byte);
+	mb.push_back (offset, 1, &msg);
+
+	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Stop %1\n", _last_tick));
 }
 
 void
@@ -387,5 +393,7 @@ MidiClockTicker::send_position_event (uint32_t midi_beats, pframes_t offset, pfr
 	MidiBuffer& mb (_midi_port->get_midi_buffer (nframes));
 	mb.push_back (offset, 3, &msg[0]);
 
-	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Song Position Sent: %1\n", midi_beats));
+	DEBUG_TRACE (DEBUG::MidiClock, string_compose ("Song Position Sent: %1 to %2 (events now %3, buf = %4)\n", midi_beats, _midi_port->name(),
+						       mb.size(), &mb));
+
 }
diff --git a/libs/ardour/utils.cc b/libs/ardour/utils.cc
index 0c98461..aa06912 100644
--- a/libs/ardour/utils.cc
+++ b/libs/ardour/utils.cc
@@ -232,6 +232,41 @@ cmp_nocase (const string& s, const string& s2)
 	return (s2.size() == s.size()) ? 0 : (s.size() < s2.size()) ? -1 : 1;
 }
 
+int cmp_nocase_utf8 (const string& s1, const string& s2)
+{
+	const char *cstr1 = s1.c_str();
+	const char *cstr2 = s2.c_str();
+	gchar *cstr1folded = NULL;
+	gchar *cstr2folded = NULL;
+	int retval;
+
+	if (!g_utf8_validate (cstr1, -1, NULL) ||
+		!g_utf8_validate (cstr2, -1, NULL)) {
+		// fall back to comparing ASCII
+		return g_ascii_strcasecmp (cstr1, cstr2);
+	}
+
+	cstr1folded = g_utf8_casefold (cstr1, -1);
+	cstr2folded = g_utf8_casefold (cstr2, -1);
+
+	if (cstr1folded && cstr2folded) {
+		retval = strcmp (cstr1folded, cstr2folded);
+	} else {
+		// this shouldn't happen, make the best of it
+		retval = g_ascii_strcasecmp (cstr1, cstr2);
+	}
+
+	if (cstr1folded) {
+		g_free (cstr1folded);
+	}
+
+	if (cstr2folded) {
+		g_free (cstr2folded);
+	}
+
+	return retval;
+}
+
 int
 touch_file (string path)
 {
diff --git a/libs/ardour/vst_plugin.cc b/libs/ardour/vst_plugin.cc
index 00cd6ef..cb40d6e 100644
--- a/libs/ardour/vst_plugin.cc
+++ b/libs/ardour/vst_plugin.cc
@@ -486,7 +486,7 @@ string
 VSTPlugin::describe_parameter (Evoral::Parameter param)
 {
 	char name[64];
-	memset (name, sizeof (name), 0);
+	memset (name, 0, sizeof (name));
 
 	/* some VST plugins expect this buffer to be zero-filled */
 
diff --git a/libs/audiographer/src/general/sample_format_converter.cc b/libs/audiographer/src/general/sample_format_converter.cc
index ea70dc6..5fe9a11 100644
--- a/libs/audiographer/src/general/sample_format_converter.cc
+++ b/libs/audiographer/src/general/sample_format_converter.cc
@@ -52,25 +52,24 @@ SampleFormatConverter<float>::init (framecnt_t max_frames, int /* type */, int d
 
 template <>
 void
-SampleFormatConverter<int32_t>::init (framecnt_t max_frames, int /*type*/, int data_width)
+SampleFormatConverter<int32_t>::init (framecnt_t max_frames, int type, int data_width)
 {
-	if(throw_level (ThrowObject) && data_width < 24) {
-		throw Exception (*this, "Trying to use SampleFormatConverter<int32_t> for data widths < 24");
+	// GDither is broken with GDither32bit if the dither depth is bigger than 24
+	if(throw_level (ThrowObject) && data_width > 24) {
+		throw Exception (*this, "Trying to use SampleFormatConverter<int32_t> a data width > 24");
 	}
-
 	init_common (max_frames);
-
-	// GDither is broken with GDither32bit if the dither depth
-	// is bigger than 24, so lets just use that...
-	dither = gdither_new (GDitherNone, channels, GDither32bit, 24);
+	dither = gdither_new ((GDitherType) type, channels, GDither32bit, data_width);
 }
 
 template <>
 void
 SampleFormatConverter<int16_t>::init (framecnt_t max_frames, int type, int data_width)
 {
-	if (throw_level (ThrowObject) && data_width != 16) {
-		throw Exception (*this, "Unsupported data width");
+	if (throw_level (ThrowObject) && data_width > 16) {
+		throw Exception (*this, boost::str(boost::format
+		    ("Data width (%1) too large for int16_t")
+		    % data_width));
 	}
 	init_common (max_frames);
 	dither = gdither_new ((GDitherType) type, channels, GDither16bit, data_width);
@@ -80,8 +79,10 @@ template <>
 void
 SampleFormatConverter<uint8_t>::init (framecnt_t max_frames, int type, int data_width)
 {
-	if (throw_level (ThrowObject) && data_width != 8) {
-		throw Exception (*this, "Unsupported data width");
+	if (throw_level (ThrowObject) && data_width > 8) {
+		throw Exception (*this, boost::str(boost::format
+		    ("Data width (%1) too large for uint8_t")
+		    % data_width));
 	}
 	init_common (max_frames);
 	dither = gdither_new ((GDitherType) type, channels, GDither8bit, data_width);
diff --git a/libs/backends/jack/jack_audiobackend.cc b/libs/backends/jack/jack_audiobackend.cc
index 86e5b9d..5e447a6 100644
--- a/libs/backends/jack/jack_audiobackend.cc
+++ b/libs/backends/jack/jack_audiobackend.cc
@@ -155,11 +155,11 @@ JACKAudioBackend::enumerate_devices () const
 }
 
 vector<float>
-JACKAudioBackend::available_sample_rates (const string& /*device*/) const
+JACKAudioBackend::available_sample_rates (const string& device) const
 {
 	vector<float> f;
 	
-	if (available()) {
+	if (device == _target_device && available()) {
 		f.push_back (sample_rate());
 		return f;
 	}
@@ -183,11 +183,11 @@ JACKAudioBackend::available_sample_rates (const string& /*device*/) const
 }
 
 vector<uint32_t>
-JACKAudioBackend::available_buffer_sizes (const string& /*device*/) const
+JACKAudioBackend::available_buffer_sizes (const string& device) const
 {
 	vector<uint32_t> s;
-	
-	if (available()) {
+		
+	if (device == _target_device && available()) {
 		s.push_back (buffer_size());
 		return s;
 	}
@@ -547,8 +547,11 @@ JACKAudioBackend::_start (bool for_latency_measurement)
 	/* Now that we have buffer size and sample rate established, the engine 
 	   can go ahead and do its stuff
 	*/
-	
-	engine.reestablish_ports ();
+
+	if (engine.reestablish_ports ()) {
+		error << _("Could not re-establish ports after connecting to JACK") << endmsg;
+		return -1;
+	}
 
 	if (!jack_port_type_get_buffer_size) {
 		warning << _("This version of JACK is old - you should upgrade to a newer version that supports jack_port_type_get_buffer_size()") << endmsg;
@@ -762,6 +765,7 @@ int
 JACKAudioBackend::jack_sync_callback (jack_transport_state_t state, jack_position_t* pos)
 {
 	TransportState tstate;
+	bool tstate_valid = true;
 
 	switch (state) {
 	case JackTransportStopped:
@@ -776,9 +780,15 @@ JACKAudioBackend::jack_sync_callback (jack_transport_state_t state, jack_positio
 	case JackTransportStarting:
 		tstate = TransportStarting;
 		break;
+	default:
+		// ignore "unofficial" states like JackTransportNetStarting (jackd2)
+		tstate_valid = false;
+		break;
 	}
 
-	return engine.sync_callback (tstate, pos->frame);
+	if (tstate_valid) {
+		return engine.sync_callback (tstate, pos->frame);
+	}
 
 	return true;
 }
@@ -1012,7 +1022,7 @@ JACKAudioBackend::disconnected (const char* why)
 }
 
 float 
-JACKAudioBackend::cpu_load() const 
+JACKAudioBackend::dsp_load() const 
 {
 	GET_PRIVATE_JACK_POINTER_RET(_priv_jack,0);
 	return jack_cpu_load (_priv_jack);
diff --git a/libs/backends/jack/jack_audiobackend.h b/libs/backends/jack/jack_audiobackend.h
index 2c77e61..d537824 100644
--- a/libs/backends/jack/jack_audiobackend.h
+++ b/libs/backends/jack/jack_audiobackend.h
@@ -89,11 +89,10 @@ class JACKAudioBackend : public AudioBackend {
     std::string control_app_name () const;
     void launch_control_app ();
 
-    int _start (bool for_latency_measurement);
     int stop ();
     int freewheel (bool);
 
-    float cpu_load() const;
+    float dsp_load() const;
 
     pframes_t sample_time ();
     pframes_t sample_time_at_cycle_start ();
@@ -272,6 +271,9 @@ class JACKAudioBackend : public AudioBackend {
     */
 
     JACKSession* _session;
+
+  protected:
+    int _start (bool for_latency_measurement);
 };
 
 } // namespace
diff --git a/libs/backends/jack/jack_connection.cc b/libs/backends/jack/jack_connection.cc
index b3d7fce..09e6c9d 100644
--- a/libs/backends/jack/jack_connection.cc
+++ b/libs/backends/jack/jack_connection.cc
@@ -143,7 +143,12 @@ JackConnection::close ()
 	if (_priv_jack) {	
 		int ret = jack_client_close (_priv_jack);
 		_jack = 0;
+
+		/* If we started JACK, it will be closing down */
+		usleep (500000);
+
 		Disconnected (""); /* EMIT SIGNAL */
+
 		return ret;
 	}
 
diff --git a/libs/evoral/src/libsmf/smf_decode.c b/libs/evoral/src/libsmf/smf_decode.c
index 0951a6e..bfba08e 100644
--- a/libs/evoral/src/libsmf/smf_decode.c
+++ b/libs/evoral/src/libsmf/smf_decode.c
@@ -490,7 +490,7 @@ static void
 note_from_int(char *buf, int note_number)
 {
 	int note, octave;
-	char *names[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
+	const char *names[] = {"C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"};
 
 	octave = note_number / 12 - 1;
 	note = note_number % 12;
diff --git a/libs/midi++2/ipmidi_port.cc b/libs/midi++2/ipmidi_port.cc
index c90a3db..c4544c2 100644
--- a/libs/midi++2/ipmidi_port.cc
+++ b/libs/midi++2/ipmidi_port.cc
@@ -36,9 +36,6 @@ typedef int socklen_t;
 inline void closesocket(int s) { ::close(s); }
 #endif
 
-#include <jack/jack.h>
-#include <jack/midiport.h>
-
 #include "pbd/xml++.h"
 #include "pbd/error.h"
 #include "pbd/failed_constructor.h"
diff --git a/libs/midi++2/midi++/ipmidi_port.h b/libs/midi++2/midi++/ipmidi_port.h
index c077170..8d5cecd 100644
--- a/libs/midi++2/midi++/ipmidi_port.h
+++ b/libs/midi++2/midi++/ipmidi_port.h
@@ -41,8 +41,6 @@
 
 #include <glibmm/threads.h>
 
-#include <jack/types.h>
-
 #include "pbd/xml++.h"
 #include "pbd/crossthread.h"
 #include "pbd/signals.h"
diff --git a/libs/midi++2/midi++/mmc.h b/libs/midi++2/midi++/mmc.h
index 01f8bf3..0f2a69d 100644
--- a/libs/midi++2/midi++/mmc.h
+++ b/libs/midi++2/midi++/mmc.h
@@ -20,7 +20,6 @@
 #ifndef __midipp_mmc_h_h__
 #define __midipp_mmc_h_h__
 
-#include <jack/types.h>
 #include "timecode/time.h"
 
 #include "pbd/signals.h"
diff --git a/libs/midi++2/midi++/port.h b/libs/midi++2/midi++/port.h
index 6d778be..f167433 100644
--- a/libs/midi++2/midi++/port.h
+++ b/libs/midi++2/midi++/port.h
@@ -22,7 +22,9 @@
 #include <string>
 #include <iostream>
 
-#include <jack/types.h>
+#include <jack/types.h> /* XXX ... desirable to get rid of this but needed for
+			 * now due to use of JackPortIsXXXX
+			 */
 
 #include "pbd/xml++.h"
 #include "pbd/crossthread.h"
diff --git a/libs/midi++2/midi++/types.h b/libs/midi++2/midi++/types.h
index 185e1e6..598bb8a 100644
--- a/libs/midi++2/midi++/types.h
+++ b/libs/midi++2/midi++/types.h
@@ -20,7 +20,6 @@
 #ifndef __midi_types_h__
 #define __midi_types_h__
 
-#include <jack/jack.h>
 #include <inttypes.h>
 
 namespace MIDI {
@@ -32,8 +31,8 @@ namespace MIDI {
 	typedef uint32_t       timestamp_t;
 
 	/** XXX: dupes from libardour */
-	typedef int64_t        framecnt_t;
-	typedef jack_nframes_t pframes_t;
+	typedef int64_t  framecnt_t;
+	typedef uint32_t pframes_t;
 
 	enum eventType {
 	    none = 0x0,
diff --git a/libs/midi++2/port.cc b/libs/midi++2/port.cc
index 1480202..90ec260 100644
--- a/libs/midi++2/port.cc
+++ b/libs/midi++2/port.cc
@@ -22,9 +22,6 @@
 #include <fcntl.h>
 #include <errno.h>
 
-#include <jack/jack.h>
-#include <jack/midiport.h>
-
 #include "pbd/xml++.h"
 #include "pbd/error.h"
 #include "pbd/failed_constructor.h"
diff --git a/libs/midi++2/wscript b/libs/midi++2/wscript
index 0abbab7..000cc39 100644
--- a/libs/midi++2/wscript
+++ b/libs/midi++2/wscript
@@ -50,7 +50,6 @@ def configure(conf):
                     'midipp', MAJOR, MINOR, MICRO)
     autowaf.configure(conf)
     autowaf.check_pkg(conf, 'cppunit', uselib_store='CPPUNIT', atleast_version='1.12.0', mandatory=False)
-    autowaf.check_pkg(conf, 'jack', uselib_store='JACK', atleast_version='0.118.2')
     autowaf.check_pkg(conf, 'libxml-2.0', uselib_store='XML')
     autowaf.check_pkg(conf, 'sigc++-2.0', uselib_store='SIGCPP', atleast_version='2.0')
 
@@ -64,13 +63,13 @@ def build(bld):
         obj              = bld.shlib(features = 'cxx cxxshlib', source=libmidi_sources)
     else:
         obj              = bld.stlib(features = 'cxx cxxstlib', source=libmidi_sources)
-        obj.cxxflags = [ '-fPIC', '-DWITH_JACK_MIDI' ]
+        obj.cxxflags = [ '-fPIC' ]
     # everybody loves JACK
     obj.export_includes = ['.']
     obj.includes     = ['.', '../surfaces/control_protocol', '../ardour' ]
     obj.name         = 'libmidipp'
     obj.target       = 'midipp'
-    obj.uselib       = 'GLIBMM SIGCPP XML JACK OSX'
+    obj.uselib       = 'GLIBMM SIGCPP XML OSX'
     obj.use          = 'libpbd libevoral libtimecode'
     obj.vnum         = LIBMIDIPP_LIB_VERSION
     obj.install_path = os.path.join(bld.env['LIBDIR'], 'ardour3')
diff --git a/libs/plugins/reasonablesynth.lv2/lv2.c b/libs/plugins/reasonablesynth.lv2/lv2.c
index b29590c..6b9c81d 100644
--- a/libs/plugins/reasonablesynth.lv2/lv2.c
+++ b/libs/plugins/reasonablesynth.lv2/lv2.c
@@ -22,6 +22,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <time.h>
 
 /* LV2 */
 #include "lv2/lv2plug.in/ns/lv2core/lv2.h"
@@ -56,6 +57,7 @@ typedef struct {
 
   double SampleRateD;
   void *synth;
+  bool xmas;
 } RSynth;
 
 /* main LV2 */
@@ -98,6 +100,16 @@ instantiate(const LV2_Descriptor*     descriptor,
   self->synth = synth_alloc();
   synth_init(self->synth, rate);
 
+
+  struct tm date;
+  time_t now;
+  time(&now);
+  localtime_r(&now, &date);
+  if (getenv("ITSXMAS") || (date.tm_mon == 11 /*dec*/ && date.tm_mday == 25)) {
+    printf("reasonable synth.lv2 says: happy holidays!\n");
+    self->xmas = true;
+  }
+
   return (LV2_Handle)self;
 }
 
@@ -146,7 +158,11 @@ run(LV2_Handle handle, uint32_t n_samples)
           written = synth_sound(self->synth, written, ev->time.frames, audio);
         }
         /* send midi message to synth */
-        synth_parse_midi(self->synth, (const uint8_t*)(ev+1), ev->body.size);
+        if (self->xmas) {
+          synth_parse_xmas(self->synth, (const uint8_t*)(ev+1), ev->body.size);
+        } else {
+          synth_parse_midi(self->synth, (const uint8_t*)(ev+1), ev->body.size);
+        }
       }
       ev = (LV2_Atom_Event const*) // lv2_atom_sequence_next()
         ((const uint8_t*)ev + sizeof(LV2_Atom_Event) + ((ev->body.size + 7) & ~7));
diff --git a/libs/plugins/reasonablesynth.lv2/rsynth.c b/libs/plugins/reasonablesynth.lv2/rsynth.c
index d2d5b3e..061d72d 100644
--- a/libs/plugins/reasonablesynth.lv2/rsynth.c
+++ b/libs/plugins/reasonablesynth.lv2/rsynth.c
@@ -71,6 +71,7 @@ typedef struct _RSSynthChannel {
   float     adsr_amp[128];
   float     phase[128];      // various use, zero'ed on note-on
   int8_t    miditable[128];  // internal, note-on/off velocity
+  int8_t    midimsgs [128];  // internal, note-off + on in same cycle
   ADSRcfg   adsr;
   void      (*synthesize) (struct _RSSynthChannel* sc,
       const uint8_t note, const float vol, const float pc,
@@ -89,6 +90,8 @@ typedef struct {
   float          kcgain;
   float          kcfilt;
   double         rate;
+  uint32_t       xmas_on;
+  uint32_t       xmas_off;
 } RSSynthesizer;
 
 
@@ -216,8 +219,10 @@ static void process_key (void *synth,
   RSSynthesizer*  rs = (RSSynthesizer*)synth;
   RSSynthChannel* sc = &rs->sc[chn];
   const int8_t vel = sc->miditable[note];
+  const int8_t msg = sc->midimsgs[note];
   const float vol = /* master_volume */ 0.25 * fabsf(vel) / 127.0;
   const float phase = sc->phase[note];
+  sc->midimsgs[note] = 0;
 
   if (phase == -10 && vel > 0) {
     // new note on
@@ -230,7 +235,7 @@ static void process_key (void *synth,
   }
   else if (phase >= -1.0 && phase <= 1.0 && vel > 0) {
     // sustain note or re-start note while adsr in progress:
-    if (sc->adsr_cnt[note] > sc->adsr.off[1]) {
+    if (sc->adsr_cnt[note] > sc->adsr.off[1] || msg == 3) {
       // x-fade to attack
       sc->adsr_amp[note] = adsr_env(sc, note);
       sc->adsr_cnt[note] = 0;
@@ -305,6 +310,7 @@ static void synth_reset_channel(RSSynthChannel* sc) {
     sc->adsr_amp[k]  = 0;
     sc->phase[k]     = -10;
     sc->miditable[k] = 0;
+    sc->midimsgs[k]  = 0;
   }
   sc->keycomp = 0;
 }
@@ -336,10 +342,12 @@ static void synth_process_midi_event(void *synth, struct rmidi_event_t *ev) {
   RSSynthesizer* rs = (RSSynthesizer*)synth;
   switch(ev->type) {
     case NOTE_ON:
+      rs->sc[ev->channel].midimsgs[ev->d.tone.note] |= 1;
       if (rs->sc[ev->channel].miditable[ev->d.tone.note] <= 0)
         rs->sc[ev->channel].miditable[ev->d.tone.note] = ev->d.tone.velocity;
       break;
     case NOTE_OFF:
+      rs->sc[ev->channel].midimsgs[ev->d.tone.note] |= 2;
       if (rs->sc[ev->channel].miditable[ev->d.tone.note] > 0)
         rs->sc[ev->channel].miditable[ev->d.tone.note] *= -1.0;
       break;
@@ -446,6 +454,44 @@ static void synth_parse_midi(void *synth, const uint8_t *data, const size_t size
   synth_process_midi_event(synth, &ev);
 }
 
+static const uint8_t jingle[] = { 71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,71 ,69 ,69 ,71 ,69 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,74 ,74 ,72 ,69 ,67 ,62 ,62 ,71 ,69 ,67 ,62 ,62 ,62 ,62 ,71 ,69 ,67 ,64 ,64 ,64 ,72 ,71 ,69 ,66 ,74 ,76 ,74 ,72 ,69 ,71 ,62 ,62 ,71 ,69 ,67 ,62 ,62 ,62 ,62 ,71 ,69 ,67 ,64 ,64 ,64 ,72 ,71 ,69 ,74 ,74 ,74 ,74 ,76 ,74 ,72 ,69 ,67 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,71 ,69 ,69 ,71 ,69 ,74 ,71 ,71 ,71 ,71 ,71 ,71 ,71 ,74 ,67 ,69 ,71 ,72 ,72 ,72 ,72 ,72 ,71 ,71 ,71 ,71 ,74 ,74 ,72 ,69 ,67 };
+
+static void synth_parse_xmas(void *synth, const uint8_t *data, const size_t size) {
+  RSSynthesizer* rs = (RSSynthesizer*)synth;
+  if (size < 2 || size > 3) return;
+  // All messages need to be 3 bytes; except program-changes: 2bytes.
+  if (size == 2 && (data[0] & 0xf0)  != 0xC0) return;
+
+  struct rmidi_event_t ev;
+
+  ev.channel = data[0]&0x0f;
+  switch (data[0] & 0xf0) {
+    case 0x80:
+      ev.type=NOTE_OFF;
+      ev.d.tone.note=jingle[rs->xmas_off++];
+      ev.d.tone.velocity=data[2]&0x7f;
+      if (rs->xmas_off >= sizeof(jingle)) rs->xmas_off = 0;
+      break;
+    case 0x90:
+      ev.type=NOTE_ON;
+      ev.d.tone.note=jingle[rs->xmas_on++];
+      ev.d.tone.velocity=data[2]&0x7f;
+      if (rs->xmas_on >= sizeof(jingle)) rs->xmas_on = 0;
+      break;
+    case 0xB0:
+      ev.type=CONTROL_CHANGE;
+      ev.d.control.param=data[1]&0x7f;
+      ev.d.control.value=data[2]&0x7f;
+      break;
+    case 0xC0:
+      ev.type=PROGRAM_CHANGE;
+      ev.d.control.value=data[1]&0x7f;
+      break;
+    default:
+      return;
+  }
+  synth_process_midi_event(synth, &ev);
+}
 /**
  * initialize the synth
  * This should be called after synth_alloc()
@@ -461,7 +507,7 @@ static void synth_init(void *synth, double rate) {
   const float tuning = 440;
   int c,k;
   for (k=0; k < 128; k++) {
-    rs->freqs[k] = (2.0 * tuning / 32.0f) * powf(2, (k - 9.0) / 12.0) / rate;
+    rs->freqs[k] = (tuning / 32.0f) * powf(2, (k - 9.0) / 12.0) / rate;
     assert(rs->freqs[k] < M_PI/2); // otherwise spatialization may phase out..
   }
   rs->kcfilt = 12.0 / rate;
@@ -470,6 +516,8 @@ static void synth_init(void *synth, double rate) {
   for (c=0; c < 16; c++) {
     synth_load(&rs->sc[c], rate, &synthesize_sineP, &piano_adsr);
   }
+  rs->xmas_on = 0;
+  rs->xmas_off = 0;
 }
 
 /**
diff --git a/libs/surfaces/control_protocol/control_protocol.cc b/libs/surfaces/control_protocol/control_protocol.cc
index e0eb57f..cd379b1 100644
--- a/libs/surfaces/control_protocol/control_protocol.cc
+++ b/libs/surfaces/control_protocol/control_protocol.cc
@@ -53,6 +53,8 @@ PBD::Signal0<void>          ControlProtocol::ClearRouteSelection;
 PBD::Signal0<void>          ControlProtocol::StepTracksDown;
 PBD::Signal0<void>          ControlProtocol::StepTracksUp;
 
+const std::string ControlProtocol::state_node_name ("Protocol");
+
 ControlProtocol::ControlProtocol (Session& s, string str)
 	: BasicUI (s)
 	, _name (str)
@@ -64,6 +66,13 @@ ControlProtocol::~ControlProtocol ()
 {
 }
 
+int
+ControlProtocol::set_active (bool yn)
+{
+	_active = yn;
+	return 0;
+}
+
 void
 ControlProtocol::next_track (uint32_t initial_id)
 {
@@ -356,5 +365,15 @@ ControlProtocol:: route_get_name (uint32_t table_index)
 list<boost::shared_ptr<Bundle> >
 ControlProtocol::bundles ()
 {
-       return list<boost::shared_ptr<Bundle> > ();
+	return list<boost::shared_ptr<Bundle> > ();
+}
+
+XMLNode&
+ControlProtocol::get_state ()
+{
+	XMLNode* node = new XMLNode (state_node_name);
+
+	node->add_property ("name", _name);
+
+	return *node;
 }
diff --git a/libs/surfaces/control_protocol/control_protocol/control_protocol.h b/libs/surfaces/control_protocol/control_protocol/control_protocol.h
index 0c84906..8dddfdc 100644
--- a/libs/surfaces/control_protocol/control_protocol/control_protocol.h
+++ b/libs/surfaces/control_protocol/control_protocol/control_protocol.h
@@ -47,8 +47,8 @@ class ControlProtocol : public PBD::Stateful, public PBD::ScopedConnectionList,
 
 	std::string name() const { return _name; }
 
-	virtual int set_active (bool yn) = 0;
-	bool get_active() const { return _active; }
+        virtual int set_active (bool yn);
+        bool active() const { return _active; }
 
 	virtual int set_feedback (bool /*yn*/) { return 0; }
 	virtual bool get_feedback () const { return false; }
@@ -133,16 +133,19 @@ class ControlProtocol : public PBD::Stateful, public PBD::ScopedConnectionList,
 	virtual void* get_gui() const { return 0; }
 	virtual void  tear_down_gui() { }
 
+        XMLNode& get_state ();
+        static const std::string state_node_name;
+
   protected:
 	std::vector<boost::shared_ptr<ARDOUR::Route> > route_table;
 	std::string _name;
-	bool _active;
 
 	void next_track (uint32_t initial_id);
 	void prev_track (uint32_t initial_id);
 
   private:
 	ControlProtocol (const ControlProtocol&); /* noncopyable */
+        bool _active;
 };
 
 extern "C" {
diff --git a/libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc b/libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc
index 550daef..f83e55c 100644
--- a/libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc
+++ b/libs/surfaces/frontier/tranzport/tranzport_control_protocol.cc
@@ -1921,9 +1921,7 @@ TranzportControlProtocol::print_noretry (int row, int col, const char *text)
 XMLNode&
 TranzportControlProtocol::get_state () 
 {
-	XMLNode* node = new XMLNode (X_("Protocol"));
-	node->add_property (X_("name"), _name);
-	return *node;
+	return ControlProtocol::get_state();
 }
 
 int
diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
index ba1858a..2ea9079 100644
--- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
@@ -80,16 +80,14 @@ GenericMidiControlProtocol::GenericMidiControlProtocol (Session& s)
 	Controllable::CreateBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::create_binding, this, _1, _2, _3));
 	Controllable::DeleteBinding.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::delete_binding, this, _1));
 
-	Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
-#if 0
-	/* XXXX SOMETHING GOES WRONG HERE (april 2012) - STILL DEBUGGING */
 	/* this signal is emitted by the process() callback, and if
 	 * send_feedback() is going to do anything, it should do it in the
 	 * context of the process() callback itself.
 	 */
 
 	Session::SendFeedback.connect_same_thread (*this, boost::bind (&GenericMidiControlProtocol::send_feedback, this));
-#endif
+	//Session::SendFeedback.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::send_feedback, this), midi_ui_context());;
+
 	/* this one is cross-thread */
 
 	Route::RemoteControlIDChange.connect (*this, MISSING_INVALIDATOR, boost::bind (&GenericMidiControlProtocol::reset_controllables, this), midi_ui_context());
@@ -466,23 +464,22 @@ GenericMidiControlProtocol::create_binding (PBD::Controllable* control, int pos,
 XMLNode&
 GenericMidiControlProtocol::get_state () 
 {
-	XMLNode* node = new XMLNode ("Protocol"); 
+	XMLNode& node (ControlProtocol::get_state());
 	char buf[32];
 
-	node->add_property (X_("name"), _name);
-	node->add_property (X_("feedback"), do_feedback ? "1" : "0");
+	node.add_property (X_("feedback"), do_feedback ? "1" : "0");
 	snprintf (buf, sizeof (buf), "%" PRIu64, _feedback_interval);
-	node->add_property (X_("feedback_interval"), buf);
+	node.add_property (X_("feedback_interval"), buf);
 	snprintf (buf, sizeof (buf), "%d", _threshold);
-	node->add_property (X_("threshold"), buf);
+	node.add_property (X_("threshold"), buf);
 
 	if (!_current_binding.empty()) {
-		node->add_property ("binding", _current_binding);
+		node.add_property ("binding", _current_binding);
 	}
 
 	XMLNode* children = new XMLNode (X_("Controls"));
 
-	node->add_child_nocopy (*children);
+	node.add_child_nocopy (*children);
 
 	Glib::Threads::Mutex::Lock lm2 (controllables_lock);
 	for (MIDIControllables::iterator i = controllables.begin(); i != controllables.end(); ++i) {
@@ -497,7 +494,7 @@ GenericMidiControlProtocol::get_state ()
 		}
 	}
 
-	return *node;
+	return node;
 }
 
 int
diff --git a/libs/surfaces/mackie/gui.cc b/libs/surfaces/mackie/gui.cc
index ebb9fd5..7425b38 100644
--- a/libs/surfaces/mackie/gui.cc
+++ b/libs/surfaces/mackie/gui.cc
@@ -453,8 +453,6 @@ MackieControlProtocolGUI::action_changed (const Glib::ustring &sPath, const Glib
 			return;
 		}
 
-		cerr << "Changed to " << i->first << " aka " << i->second << endl;
-
 		Glib::RefPtr<Gtk::Action> act = ActionManager::get_action (i->second.c_str());
 
 		if (act) {
@@ -504,8 +502,6 @@ MackieControlProtocolGUI::surface_combo_changed ()
 
 	/* update ipMIDI field */
 
-	cerr << "New device called " << _cp.device_info().name() << " with ipMIDI ? " << _cp.device_info().uses_ipmidi() << endl;
-
 	ipmidi_base_port_spinner.set_sensitive (_cp.device_info().uses_ipmidi());
 }
 
@@ -522,7 +518,6 @@ MackieControlProtocolGUI::profile_combo_changed ()
 void
 MackieControlProtocolGUI::ipmidi_spinner_changed ()
 {
-	cerr << "Set IP MIDI base to " << ipmidi_base_port_spinner.get_value() << endl;
 	_cp.set_ipmidi_base ((int16_t) lrintf (ipmidi_base_port_spinner.get_value()));
 }
 
diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
index b55ac74..e9bef5a 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.cc
+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
@@ -96,8 +96,6 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
 	, AbstractUI<MackieControlUIRequest> ("mackie")
 	, _current_initial_bank (0)
 	, _timecode_type (ARDOUR::AnyTime::BBT)
-	, _input_bundle (new ARDOUR::Bundle (_("Mackie Control In"), true))
-	, _output_bundle (new ARDOUR::Bundle (_("Mackie Control Out"), false))
 	, _gui (0)
 	, _zoom_mode (false)
 	, _scrub_mode (false)
@@ -109,6 +107,8 @@ MackieControlProtocol::MackieControlProtocol (Session& session)
 	, needs_ipmidi_restart (false)
 	, _metering_active (true)
 	, _initialized (false)
+	, _surfaces_state (0)
+	, _surfaces_version (0)
 {
 	DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::MackieControlProtocol\n");
 
@@ -132,7 +132,7 @@ MackieControlProtocol::~MackieControlProtocol()
 	DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol tear_down_gui ()\n");
 	tear_down_gui ();
 
-	_active = false;
+	delete _surfaces_state;
 
 	/* stop event loop */
 	DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::~MackieControlProtocol BaseUI::quit ()\n");
@@ -383,7 +383,7 @@ MackieControlProtocol::set_active (bool yn)
 {
 	DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active init with yn: '%1'\n", yn));
 
-	if (yn == _active) {
+	if (yn == active()) {
 		return 0;
 	}
 
@@ -397,7 +397,6 @@ MackieControlProtocol::set_active (bool yn)
 			return -1;
 		}
 		connect_session_signals ();
-		_active = true;
 		update_surfaces ();
 		
 		/* set up periodic task for metering and automation
@@ -411,10 +410,11 @@ MackieControlProtocol::set_active (bool yn)
 
 		BaseUI::quit ();
 		close ();
-		_active = false;
 
 	}
 
+	ControlProtocol::set_active (yn);
+
 	DEBUG_TRACE (DEBUG::MackieControl, string_compose("MackieControlProtocol::set_active done with yn: '%1'\n", yn));
 
 	return 0;
@@ -423,7 +423,7 @@ MackieControlProtocol::set_active (bool yn)
 bool
 MackieControlProtocol::periodic ()
 {
-	if (!_active) {
+	if (!active()) {
 		return false;
 	}
 
@@ -526,7 +526,7 @@ void
 MackieControlProtocol::update_surfaces()
 {
 	DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::update_surfaces() init\n");
-	if (!_active) {
+	if (!active()) {
 		return;
 	}
 
@@ -609,34 +609,36 @@ MackieControlProtocol::set_profile (const string& profile_name)
 }	
 
 int
-MackieControlProtocol::set_device (const string& device_name, bool allow_activation)
+MackieControlProtocol::set_device_info (const string& device_name)
 {
 	map<string,DeviceInfo>::iterator d = DeviceInfo::device_info.find (device_name);
 
-	DEBUG_TRACE (DEBUG::MackieControl, string_compose ("new device chosen %1, activation allowed ? %2\n",
-							   device_name, allow_activation));
+	DEBUG_TRACE (DEBUG::MackieControl, string_compose ("new device chosen %1\n", device_name));
 
 	if (d == DeviceInfo::device_info.end()) {
 		return -1;
 	}
 	
-	if (_active) {
-		clear_ports ();
-		clear_surfaces ();
+	_device_info = d->second;
+
+	return 0;
+}
+
+int
+MackieControlProtocol::set_device (const string& device_name)
+{
+	if (set_device_info (device_name)) {
+		return -1;
 	}
 
-	_device_info = d->second;
+	clear_surfaces ();
 
-	if (allow_activation) {
-		set_active (true);
-	} else {
-		if (_active) {
-			if (create_surfaces ()) {
-				return -1;
-			}
-			switch_banks (0, true);
-		}
+	if (create_surfaces ()) {
+		return -1;
 	}
+
+	switch_banks (0, true);
+
 	return 0;
 }
 
@@ -665,6 +667,10 @@ MackieControlProtocol::create_surfaces ()
 			return -1;
 		}
 
+		if (_surfaces_state) {
+			surface->set_state (*_surfaces_state, _surfaces_version);
+		}
+
 		{
 			Glib::Threads::Mutex::Lock lm (surfaces_lock);
 			surfaces.push_back (surface);
@@ -681,6 +687,10 @@ MackieControlProtocol::create_surfaces ()
 		stype = ext;
 
 		if (!_device_info.uses_ipmidi()) {
+
+			_input_bundle.reset (new ARDOUR::Bundle (_("Mackie Control In"), true));
+			_output_bundle.reset (new ARDOUR::Bundle (_("Mackie Control Out"), false));
+
 			_input_bundle->add_channel (
 				surface->port().input_port().name(),
 				ARDOUR::DataType::MIDI,
@@ -692,6 +702,16 @@ MackieControlProtocol::create_surfaces ()
 				ARDOUR::DataType::MIDI,
 				session->engine().make_port_name_non_relative (surface->port().output_port().name())
 				);
+
+			session->BundleAdded (_input_bundle);
+			session->BundleAdded (_output_bundle);
+
+		} else {
+			_input_bundle.reset ((ARDOUR::Bundle*) 0);
+			_output_bundle.reset ((ARDOUR::Bundle*) 0);
+
+			session->BundleRemoved (_input_bundle);
+			session->BundleRemoved (_output_bundle);
 		}
 
 		int fd;
@@ -716,9 +736,6 @@ MackieControlProtocol::create_surfaces ()
 void 
 MackieControlProtocol::close()
 {
-	clear_ports ();
-
-	port_connections.drop_connections ();
 	session_connections.drop_connections ();
 	route_connections.drop_connections ();
 	periodic_connection.disconnect ();
@@ -729,38 +746,42 @@ MackieControlProtocol::close()
 XMLNode& 
 MackieControlProtocol::get_state()
 {
+	XMLNode& node (ControlProtocol::get_state());
+
 	DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state init\n");
 	char buf[16];
 
-	// add name of protocol
-	XMLNode* node = new XMLNode (X_("Protocol"));
-	node->add_property (X_("name"), ARDOUR::ControlProtocol::_name);
-
 	// add current bank
 	snprintf (buf, sizeof (buf), "%d", _current_initial_bank);
-	node->add_property (X_("bank"), buf);
+	node.add_property (X_("bank"), buf);
 
 	// ipMIDI base port (possibly not used)
 	snprintf (buf, sizeof (buf), "%d", _ipmidi_base);
-	node->add_property (X_("ipmidi-base"), buf);
+	node.add_property (X_("ipmidi-base"), buf);
+
+	node.add_property (X_("device-profile"), _device_profile.name());
+	node.add_property (X_("device-name"), _device_info.name());
+
+	XMLNode* snode = new XMLNode (X_("Surfaces"));
+	for (Surfaces::iterator s = surfaces.begin(); s != surfaces.end(); ++s) {
+		snode->add_child_nocopy ((*s)->get_state());
+	}
 
-	node->add_property (X_("device-profile"), _device_profile.name());
-	node->add_property (X_("device-name"), _device_info.name());
+	node.add_child_nocopy (*snode);
 
 	DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::get_state done\n");
 
-	return *node;
+	return node;
 }
 
 int 
-MackieControlProtocol::set_state (const XMLNode & node, int /*version*/)
+MackieControlProtocol::set_state (const XMLNode & node, int version)
 {
-	DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", _active));
+	DEBUG_TRACE (DEBUG::MackieControl, string_compose ("MackieControlProtocol::set_state: active %1\n", active()));
 
 	int retval = 0;
 	const XMLProperty* prop;
 	uint32_t bank = 0;
-	bool active = _active;
 
 	if ((prop = node.property (X_("ipmidi-base"))) != 0) {
 		set_ipmidi_base (atoi (prop->value()));
@@ -771,24 +792,26 @@ MackieControlProtocol::set_state (const XMLNode & node, int /*version*/)
 		bank = atoi (prop->value());
 	}
 	
-	if ((prop = node.property (X_("active"))) != 0) {
-		active = string_is_affirmative (prop->value());
-	}
-
 	if ((prop = node.property (X_("device-name"))) != 0) {
-		set_device (prop->value(), false);
+		set_device_info (prop->value());
 	}
 
 	if ((prop = node.property (X_("device-profile"))) != 0) {
 		set_profile (prop->value());
 	}
+	
+	XMLNode* snode = node.child (X_("Surfaces"));
+	
+	delete _surfaces_state;
+	_surfaces_state = 0;
 
-	set_active (active);
-
-	if (_active) {
-		switch_banks (bank, true);
+	if (snode) {
+		_surfaces_state = new XMLNode (*snode);
+		_surfaces_version = version;
 	}
 
+	switch_banks (bank, true);
+	
 	DEBUG_TRACE (DEBUG::MackieControl, "MackieControlProtocol::set_state done\n");
 
 	return retval;
@@ -1035,8 +1058,12 @@ list<boost::shared_ptr<ARDOUR::Bundle> >
 MackieControlProtocol::bundles ()
 {
 	list<boost::shared_ptr<ARDOUR::Bundle> > b;
-	b.push_back (_input_bundle);
-	b.push_back (_output_bundle);
+
+	if (_input_bundle) {
+		b.push_back (_input_bundle);
+		b.push_back (_output_bundle);
+	}
+
 	return b;
 }
 
@@ -1259,8 +1286,10 @@ MackieControlProtocol::midi_input_handler (IOCondition ioc, MIDI::Port* port)
 void
 MackieControlProtocol::clear_ports ()
 {
-	_input_bundle->remove_channels ();
-	_output_bundle->remove_channels ();
+	if (_input_bundle) {
+		_input_bundle->remove_channels ();
+		_output_bundle->remove_channels ();
+	}
 
 	for (PortSources::iterator i = port_sources.begin(); i != port_sources.end(); ++i) {
 		g_source_destroy (*i);
@@ -1581,7 +1610,7 @@ MackieControlProtocol::set_ipmidi_base (int16_t portnum)
 	   to restart.
 	*/
 
-	if (_active && _device_info.uses_ipmidi()) {
+	if (active() && _device_info.uses_ipmidi()) {
 		needs_ipmidi_restart = true;
 	}
 }
@@ -1589,7 +1618,6 @@ MackieControlProtocol::set_ipmidi_base (int16_t portnum)
 int
 MackieControlProtocol::ipmidi_restart ()
 {
-	clear_ports ();
 	clear_surfaces ();
 	if (create_surfaces ()) {
 		return -1;
@@ -1602,6 +1630,7 @@ MackieControlProtocol::ipmidi_restart ()
 void
 MackieControlProtocol::clear_surfaces ()
 {
+	clear_ports ();
 	Glib::Threads::Mutex::Lock lm (surfaces_lock);
 	surfaces.clear ();	
 }
diff --git a/libs/surfaces/mackie/mackie_control_protocol.h b/libs/surfaces/mackie/mackie_control_protocol.h
index 4669247..e1a71a2 100644
--- a/libs/surfaces/mackie/mackie_control_protocol.h
+++ b/libs/surfaces/mackie/mackie_control_protocol.h
@@ -120,7 +120,7 @@ class MackieControlProtocol
 	Mackie::DeviceProfile& device_profile() { return _device_profile; }
 
 	int set_active (bool yn);
-	int  set_device (const std::string&, bool allow_activation = true);
+	int  set_device (const std::string&);
         void set_profile (const std::string&);
 
 	FlipMode flip_mode () const { return _flip_mode; }
@@ -262,7 +262,6 @@ class MackieControlProtocol
 	uint32_t                 _current_initial_bank;
 	PBD::ScopedConnectionList audio_engine_connections;
 	PBD::ScopedConnectionList session_connections;
-	PBD::ScopedConnectionList port_connections;
 	PBD::ScopedConnectionList route_connections;
 	PBD::ScopedConnectionList gui_connections;
 	// timer for two quick marker left presses
@@ -288,8 +287,9 @@ class MackieControlProtocol
 	bool                      needs_ipmidi_restart;
 	bool                     _metering_active;
 	bool                     _initialized;
-
 	ARDOUR::RouteNotificationList _last_selected_routes;
+        XMLNode*                 _surfaces_state;
+        int                      _surfaces_version;
 
 	int create_surfaces ();
 	bool periodic();
@@ -303,7 +303,8 @@ class MackieControlProtocol
 	void _gui_track_selection_changed (ARDOUR::RouteNotificationList*, bool save_list);
 	int ipmidi_restart ();
         void initialize ();
-	
+        int set_device_info (const std::string& device_name);
+
 	/* BUTTON HANDLING */
 
 	typedef std::set<uint32_t> DownButtonList;
diff --git a/libs/surfaces/mackie/surface.cc b/libs/surfaces/mackie/surface.cc
index 507491d..694c73b 100644
--- a/libs/surfaces/mackie/surface.cc
+++ b/libs/surfaces/mackie/surface.cc
@@ -141,6 +141,39 @@ Surface::~Surface ()
 	DEBUG_TRACE (DEBUG::MackieControl, "Surface::~Surface done\n");
 }
 
+XMLNode&
+Surface::get_state()
+{
+	char buf[64];
+	snprintf (buf, sizeof (buf), X_("surface-%u"), _number);
+	XMLNode* node = new XMLNode (buf);
+
+	node->add_child_nocopy (_port->get_state());
+
+	return *node;
+}
+
+int
+Surface::set_state (const XMLNode& node, int version)
+{
+	char buf[64];
+	snprintf (buf, sizeof (buf), X_("surface-%u"), _number);
+	XMLNode* mynode = node.child (buf);
+
+	if (!mynode) {
+		return 0;
+	}
+
+	XMLNode* portnode = mynode->child (X_("Port"));
+	if (portnode) {
+		if (_port->set_state (*portnode, version)) {
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
 const MidiByteArray& 
 Surface::sysex_hdr() const
 {
@@ -589,12 +622,6 @@ Surface::turn_it_on ()
 }
 
 void 
-Surface::handle_port_inactive (SurfacePort*)
-{
-	_active = false;
-}
-
-void 
 Surface::write_sysex (const MidiByteArray & mba)
 {
 	if (mba.empty()) {
diff --git a/libs/surfaces/mackie/surface.h b/libs/surfaces/mackie/surface.h
index ecaa417..1ed83ae 100644
--- a/libs/surfaces/mackie/surface.h
+++ b/libs/surfaces/mackie/surface.h
@@ -3,6 +3,7 @@
 
 #include <stdint.h>
 
+#include "pbd/xml++.h"
 #include "midi++/types.h"
 
 #include "control_protocol/types.h"
@@ -92,9 +93,6 @@ public:
 	/// unless it's already connected
 	void connect_to_signals ();
 
-	/// notification from a MackiePort that it's now inactive
-	void handle_port_inactive(Mackie::SurfacePort *);
-
 	/// write a sysex message
 	void write_sysex (const MidiByteArray& mba);
 	void write_sysex (MIDI::byte msg);
@@ -149,6 +147,9 @@ public:
         void notify_metering_state_changed();
 	void turn_it_on ();
 
+	XMLNode& get_state ();
+	int set_state (const XMLNode&, int version);
+
   protected:
 	
   private:
diff --git a/libs/surfaces/mackie/surface_port.cc b/libs/surfaces/mackie/surface_port.cc
index 508f501..013a001 100644
--- a/libs/surfaces/mackie/surface_port.cc
+++ b/libs/surfaces/mackie/surface_port.cc
@@ -51,11 +51,12 @@ using namespace ARDOUR;
 SurfacePort::SurfacePort (Surface& s)
 	: _surface (&s)
 {
-
 	if (_surface->mcp().device_info().uses_ipmidi()) {
 		_input_port = new MIDI::IPMIDIPort (_surface->mcp().ipmidi_base() +_surface->number());
 		_output_port = _input_port;
+
 	} else {
+		
 		_async_in  = AudioEngine::instance()->register_input_port (DataType::MIDI, string_compose (_("%1 in"),  _surface->name()), true);
 		_async_out = AudioEngine::instance()->register_output_port (DataType::MIDI, string_compose (_("%1 out"),  _surface->name()), true);
 
@@ -70,21 +71,71 @@ SurfacePort::SurfacePort (Surface& s)
 
 SurfacePort::~SurfacePort()
 {
-	if (_surface->mcp().device_info().uses_ipmidi()) {
+	if (dynamic_cast<MIDI::IPMIDIPort*>(_input_port)) {
 		delete _input_port;
 	} else {
 
 		if (_async_in) {
 			AudioEngine::instance()->unregister_port (_async_in);
-			_async_in.reset ();
+			_async_in.reset ((ARDOUR::Port*) 0);
 		}
 		
 		if (_async_out) {
 			_output_port->drain (10000);
 			AudioEngine::instance()->unregister_port (_async_out);
-			_async_out.reset ();
+			_async_out.reset ((ARDOUR::Port*) 0);
+		}
+	}
+}
+
+XMLNode&
+SurfacePort::get_state ()
+{
+	XMLNode* node = new XMLNode (X_("Port"));
+
+	if (dynamic_cast<MIDI::IPMIDIPort*>(_input_port)) {
+		/* no state required for IPMidi ports */
+		return *node;
+	}
+
+	XMLNode* child;
+
+	child = new XMLNode (X_("Input"));
+	child->add_child_nocopy (_async_in->get_state());
+	node->add_child_nocopy (*child);
+	
+
+	child = new XMLNode (X_("Output"));
+	child->add_child_nocopy (_async_out->get_state());
+	node->add_child_nocopy (*child);
+
+	return *node;
+}
+
+int
+SurfacePort::set_state (const XMLNode& node, int version)
+{
+	if (dynamic_cast<MIDI::IPMIDIPort*>(_input_port)) {
+		return 0;
+	}
+
+	XMLNode* child;
+
+	if ((child = node.child (X_("Input"))) != 0) {
+		XMLNode* portnode = child->child (Port::state_node_name.c_str());
+		if (portnode) {
+			_async_in->set_state (*portnode, version);
 		}
 	}
+
+	if ((child = node.child (X_("Output"))) != 0) {
+		XMLNode* portnode = child->child (Port::state_node_name.c_str());
+		if (portnode) {
+			_async_out->set_state (*portnode, version);
+		}
+	}
+
+	return 0;
 }
 
 // wrapper for one day when strerror_r is working properly
diff --git a/libs/surfaces/mackie/surface_port.h b/libs/surfaces/mackie/surface_port.h
index 751ee84..b361294 100644
--- a/libs/surfaces/mackie/surface_port.h
+++ b/libs/surfaces/mackie/surface_port.h
@@ -50,15 +50,18 @@ class Surface;
 class SurfacePort 
 {
 public:
-	SurfacePort (Mackie::Surface&);
-	virtual ~SurfacePort();
-	
-	/// an easier way to output bytes via midi
-	int write (const MidiByteArray&);
+    SurfacePort (Mackie::Surface&);
+    virtual ~SurfacePort();
+    
+    /// an easier way to output bytes via midi
+    int write (const MidiByteArray&);
 	
     MIDI::Port& input_port() const { return *_input_port; }
     MIDI::Port& output_port() const { return *_output_port; }
 
+    XMLNode& get_state ();
+    int set_state (const XMLNode&, int version);
+
 protected:
 
 private:
diff --git a/libs/surfaces/osc/osc.cc b/libs/surfaces/osc/osc.cc
index 0c7c845..37fe071 100644
--- a/libs/surfaces/osc/osc.cc
+++ b/libs/surfaces/osc/osc.cc
@@ -30,6 +30,7 @@
 
 #include <glibmm/miscutils.h>
 
+#include <pbd/convert.h>
 #include <pbd/pthread_utils.h>
 #include <pbd/file_utils.h>
 #include <pbd/failed_constructor.h>
@@ -71,22 +72,20 @@ static void error_callback(int, const char *, const char *)
 #endif
 
 OSC::OSC (Session& s, uint32_t port)
-	: ControlProtocol (s, "OSC")
+	: ControlProtocol (s, X_("Open Sound Control (OSC)"))
 	, AbstractUI<OSCUIRequest> ("osc")
+	, local_server (0)
+	, remote_server (0)
 	, _port(port)
+	, _ok (true)
+	, _shutdown (false)
+	, _osc_server (0)
+	, _osc_unix_server (0)
+	, _namespace_root ("/ardour")
+	, _send_route_changes (true)
 {
 	_instance = this;
-	_shutdown = false;
-	_osc_server = 0;
-	_osc_unix_server = 0;
-	_namespace_root = "/ardour";
-	_send_route_changes = true;
 
-	/* glibmm hack */
-	local_server = 0;
-	remote_server = 0;
-
-	// "Application Hooks"
 	session_loaded (s);
 	session->Exported.connect (*this, MISSING_INVALIDATOR, boost::bind (&OSC::session_exported, this, _1, _2), this);
 }
@@ -113,11 +112,21 @@ OSC::do_request (OSCUIRequest* req)
 int
 OSC::set_active (bool yn)
 {
-	if (yn) {
-		return start ();
-	} else {
-		return stop ();
+	if (yn != active()) {
+
+		if (yn) {
+			if (start ()) {
+				return -1;
+			}
+		} else {
+			if (stop ()) {
+				return -1;
+			}
+		}
+		
 	}
+
+	return ControlProtocol::set_active (yn);
 }
 
 bool
@@ -1059,16 +1068,26 @@ OSC::route_plugin_parameter_print (int rid, int piid, int par)
 XMLNode& 
 OSC::get_state () 
 {
-	XMLNode* node = new XMLNode ("Protocol"); 
-
-	node->add_property (X_("name"), "Open Sound Control (OSC)");
-	node->add_property (X_("feedback"), _send_route_changes ? "1" : "0");
+	XMLNode& node (ControlProtocol::get_state());
 
-	return *node;
+	node.add_property (X_("feedback"), _send_route_changes ? "1" : "0");
+	return node;
 }
 
 int 
-OSC::set_state (const XMLNode&, int /*version*/)
+OSC::set_state (const XMLNode& node, int /*version*/)
 {
+	const XMLProperty* prop = node.property (X_("feedback"));
+
+	if (prop) {
+		if (PBD::string_is_affirmative (prop->value())) {
+			_send_route_changes = true;
+		} else {
+			_send_route_changes = false;
+		}
+	} else {
+		/* leave it alone */
+	}
+	      
 	return 0;
 }
diff --git a/libs/surfaces/tranzport/state.cc b/libs/surfaces/tranzport/state.cc
index 7995e1a..119e795 100644
--- a/libs/surfaces/tranzport/state.cc
+++ b/libs/surfaces/tranzport/state.cc
@@ -50,9 +50,7 @@ using namespace PBD;
 XMLNode&
 TranzportControlProtocol::get_state () 
 {
-	XMLNode* node = new XMLNode (X_("Protocol"));
-	node->add_property (X_("name"), _name);
-	return *node;
+	return ControlProtocol::get_state();
 }
 
 int
diff --git a/libs/surfaces/wiimote/wiimote.cc b/libs/surfaces/wiimote/wiimote.cc
index 68f2125..963bf90 100644
--- a/libs/surfaces/wiimote/wiimote.cc
+++ b/libs/surfaces/wiimote/wiimote.cc
@@ -65,7 +65,8 @@ WiimoteControlProtocol::set_active (bool yn)
 	DEBUG_TRACE (DEBUG::WiimoteControl, string_compose ("WiimoteControlProtocol::set_active init with yn: '%1'\n", yn));
 
 	/* do nothing if the active state is not changing */
-	if (yn == _active) {
+
+	if (yn == active()) {
 		return 0;
 	}
 
@@ -77,8 +78,7 @@ WiimoteControlProtocol::set_active (bool yn)
 		result = stop ();
 	}
 
-	/* remember new active state */
-	_active = yn;
+	ControlProtocol::set_active (yn);
 
 	DEBUG_TRACE (DEBUG::WiimoteControl, "WiimoteControlProtocol::set_active done\n");
 
@@ -88,10 +88,9 @@ WiimoteControlProtocol::set_active (bool yn)
 XMLNode&
 WiimoteControlProtocol::get_state ()
 {
-	XMLNode *node = new XMLNode ("Protocol");
-	node->add_property (X_("name"), ARDOUR::ControlProtocol::_name);
-	node->add_property (X_("feedback"), "0");
-	return *node;
+	XMLNode& node (ControlProtocol::get_state());
+	node.add_property (X_("feedback"), "0");
+	return node;
 }
 
 int
diff --git a/tools/fmt-bindings b/tools/fmt-bindings
index cd69e04..ab4595d 100755
--- a/tools/fmt-bindings
+++ b/tools/fmt-bindings
@@ -369,6 +369,8 @@ if ($html) {
 
 $boilerplate_header = <<END_HEADER;
 \\documentclass[10pt,landscape]{article}
+%\\documentclass[10pt,landscape,a4paper]{article}
+%\\documentclass[10pt,landscape,letterpaper]{article}
 \\usepackage{multicol}
 \\usepackage{calc}
 \\usepackage{ifthen}
@@ -387,7 +389,7 @@ $boilerplate_header = <<END_HEADER;
 % if using A4 paper. (This probably isnott strictly necessary.)
 % If using another size paper, use default 1cm margins.
 \\ifthenelse{\\lengthtest { \\paperwidth = 11in}}
-	{ \\geometry{top=.5in,left=1in,right=0in,bottom=.5in} }
+	{ \\geometry{top=.5in,left=.5in,right=.5in,bottom=.5in} }
 	{\\ifthenelse{ \\lengthtest{ \\paperwidth = 297mm}}
 		{\\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
 		{\\geometry{top=1cm,left=1cm,right=1cm,bottom=1cm} }
@@ -431,12 +433,11 @@ $boilerplate_footer = <<END_FOOTER;
 \\rule{0.3\\linewidth}{0.25pt}
 \\scriptsize
 
-Copyright \\copyright\\ 2009 ardour.org
+Copyright \\copyright\\ 2013 ardour.org
 
 % Should change this to be date of file, not current date.
-%\\verb!$Revision: 1.13 $, $Date: 2008/05/29 06:11:56 $.!
 
-http://ardour.org/manual
+http://manual.ardour.org
 
 \\end{multicols}
 \\end{document}
diff --git a/wscript b/wscript
index 99bd46d..e68780f 100644
--- a/wscript
+++ b/wscript
@@ -132,7 +132,17 @@ def set_compiler_flags (conf,opt):
     #
 
     build_host_supports_sse = False
+
+    # Flags necessary for building
+    compiler_flags = []     # generic
+    c_flags = []            # C-specific
+    cxx_flags = []          # C++-specific
+    linker_flags = []
+
+    # Optimization flags (overridable)
     optimization_flags = []
+
+    # Debugging flags
     debug_flags = []
 
     u = os.uname ()
@@ -145,10 +155,10 @@ def set_compiler_flags (conf,opt):
     
     if conf.options.cxx11:
         conf.check_cxx(cxxflags=["-std=c++11"])
-        conf.env.append_unique('CXXFLAGS', ['-std=c++11'])
+        cxx_flags.append('-std=c++11')
         if platform == "darwin":
-            conf.env.append_unique('CXXFLAGS', ['-stdlib=libc++'])
-            conf.env.append_unique('LINKFLAGS', ['-lc++'])
+            cxx_flags.append('-stdlib=libc++')
+            link_flags.append('-lc++')
             # Prevents visibility issues in standard headers
             conf.define("_DARWIN_C_SOURCE", 1)
 
@@ -156,7 +166,7 @@ def set_compiler_flags (conf,opt):
         # Silence warnings about the non-existing osx clang compiler flags
         # -compatibility_version and -current_version.  These are Waf
         # generated and not needed with clang
-        conf.env.append_unique ("CXXFLAGS", ["-Qunused-arguments"])
+        cxx_flags.append("-Qunused-arguments")
         
     if opt.gprofile:
         debug_flags = [ '-pg' ]
@@ -182,16 +192,15 @@ def set_compiler_flags (conf,opt):
             else:
                 conf.env['build_target'] = 'mountainlion'
         else:
-            if re.search ("x86_64", cpu) != None:
-                conf.env['build_target'] = 'x86_64'
-            elif re.search("i[0-5]86", cpu) != None:
-                conf.env['build_target'] = 'i386'
-            elif re.search("powerpc", cpu) != None:
-                conf.env['build_target'] = 'powerpc'
-            elif re.search("arm", cpu) != None:
-                conf.env['build_target'] = 'arm'
+            match = re.search(
+                    "(?P<cpu>i[0-6]86|x86_64|powerpc|ppc|ppc64|arm|s390x?)",
+                    cpu)
+            if (match):
+                conf.env['build_target'] = match.group("cpu")
+                if re.search("i[0-5]86", conf.env['build_target']):
+                    conf.env['build_target'] = "i386"
             else:
-                conf.env['build_target'] = 'i686'
+                conf.env['build_target'] = 'none'
     else:
         conf.env['build_target'] = opt.dist_target
 
@@ -200,8 +209,7 @@ def set_compiler_flags (conf,opt):
         # stupid OS X 10.6 has a bug in math.h that prevents llrint and friends
         # from being visible.
         # 
-        debug_flags.append ('-U__STRICT_ANSI__')
-        optimization_flags.append ('-U__STRICT_ANSI__')
+        compiler_flags.append ('-U__STRICT_ANSI__')
 
     if cpu == 'powerpc' and conf.env['build_target'] != 'none':
         #
@@ -213,12 +221,12 @@ def set_compiler_flags (conf,opt):
             if platform == 'darwin':
                 # optimization_flags.extend ([ "-mcpu=7450", "-faltivec"])
                 # to support g3s but still have some optimization for above
-                optimization_flags.extend ([ "-mcpu=G3", "-mtune=7450"])
+                compiler_flags.extend ([ "-mcpu=G3", "-mtune=7450"])
             else:
-                optimization_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
+                compiler_flags.extend ([ "-mcpu=7400", "-maltivec", "-mabi=altivec"])
         else:
-            optimization_flags.extend([ "-mcpu=750", "-mmultiple" ])
-        optimization_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
+            compiler_flags.extend([ "-mcpu=750", "-mmultiple" ])
+        compiler_flags.extend (["-mhard-float", "-mpowerpc-gfxopt"])
         optimization_flags.extend (["-Os"])
 
     elif ((re.search ("i[0-9]86", cpu) != None) or (re.search ("x86_64", cpu) != None)) and conf.env['build_target'] != 'none':
@@ -231,8 +239,7 @@ def set_compiler_flags (conf,opt):
         #
 
         if (re.search ("(i[0-9]86|x86_64)", cpu) != None):
-            debug_flags.append ("-DARCH_X86")
-            optimization_flags.append ("-DARCH_X86")
+            compiler_flags.append ("-DARCH_X86")
 
         if platform == 'linux' :
 
@@ -246,32 +253,29 @@ def set_compiler_flags (conf,opt):
                 x86_flags = flag_line.split (": ")[1:][0].split ()
 
                 if "mmx" in x86_flags:
-                    optimization_flags.append ("-mmmx")
+                    compiler_flags.append ("-mmmx")
                 if "sse" in x86_flags:
                     build_host_supports_sse = True
                 if "3dnow" in x86_flags:
-                    optimization_flags.append ("-m3dnow")
+                    compiler_flags.append ("-m3dnow")
 
             if cpu == "i586":
-                optimization_flags.append ("-march=i586")
+                compiler_flags.append ("-march=i586")
             elif cpu == "i686":
-                optimization_flags.append ("-march=i686")
+                compiler_flags.append ("-march=i686")
 
         if not is_clang and ((conf.env['build_target'] == 'i686') or (conf.env['build_target'] == 'x86_64')) and build_host_supports_sse:
-            optimization_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
-            debug_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
+            compiler_flags.extend (["-msse", "-mfpmath=sse", "-DUSE_XMMINTRIN"])
 
     # end of processor-specific section
 
     # optimization section
     if conf.env['FPU_OPTIMIZATION']:
         if sys.platform == 'darwin':
-            optimization_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
-            debug_flags.append ("-DBUILD_VECLIB_OPTIMIZATIONS");
-            conf.env.append_value('LINKFLAGS', "-framework Accelerate")
+            compiler_flags.append("-DBUILD_VECLIB_OPTIMIZATIONS");
+            linker_flags.append("-framework Accelerate")
         elif conf.env['build_target'] == 'i686' or conf.env['build_target'] == 'x86_64':
-            optimization_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
-            debug_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
+            compiler_flags.append ("-DBUILD_SSE_OPTIMIZATIONS")
         if not build_host_supports_sse:
             print("\nWarning: you are building Ardour with SSE support even though your system does not support these instructions. (This may not be an error, especially if you are a package maintainer)")
 
@@ -290,9 +294,9 @@ def set_compiler_flags (conf,opt):
 
     if opt.lxvst:
         if conf.env['build_target'] == 'x86_64':
-            conf.env.append_value('CXXFLAGS', "-DLXVST_64BIT")
+            compiler_flags.append("-DLXVST_64BIT")
         else:
-            conf.env.append_value('CXXFLAGS', "-DLXVST_32BIT")
+            compiler_flags.append("-DLXVST_32BIT")
 
     #
     # a single way to test if we're on OS X
@@ -302,18 +306,15 @@ def set_compiler_flags (conf,opt):
         conf.define ('IS_OSX', 1)
         # force tiger or later, to avoid issues on PPC which defaults
         # back to 10.1 if we don't tell it otherwise.
-        
-        conf.env.append_value('CFLAGS', "-DMAC_OS_X_VERSION_MIN_REQUIRED=1040")
-        conf.env.append_value('CXXFLAGS', "-DMAC_OS_X_VERSION_MIN_REQUIRED=1040")
-        conf.env.append_value('CXXFLAGS', '-mmacosx-version-min=10.4')
-        conf.env.append_value('CFLAGS', '-mmacosx-version-min=10.4')
 
+        compiler_flags.extend(
+                ("-DMAC_OS_X_VERSION_MIN_REQUIRED=1040",
+                 '-mmacosx-version-min=10.4'))
 
     elif conf.env['build_target'] in [ 'lion', 'mountainlion' ]:
-        conf.env.append_value('CFLAGS', "-DMAC_OS_X_VERSION_MIN_REQUIRED=1070")
-        conf.env.append_value('CXXFLAGS', "-DMAC_OS_X_VERSION_MIN_REQUIRED=1070")
-        conf.env.append_value('CXXFLAGS', '-mmacosx-version-min=10.7')
-        conf.env.append_value('CFLAGS', '-mmacosx-version-min=10.7')
+        compiler_flags.extend(
+                ("-DMAC_OS_X_VERSION_MIN_REQUIRED=1070",
+                 '-mmacosx-version-min=10.7'))
     else:
         conf.define ('IS_OSX', 0)
 
@@ -350,26 +351,15 @@ def set_compiler_flags (conf,opt):
                 "-fstrength-reduce"
                 ]
 
-    if opt.debug:
-        conf.env.append_value('CFLAGS', debug_flags)
-        conf.env.append_value('CXXFLAGS', debug_flags)
-        conf.env.append_value('LINKFLAGS', debug_flags)
-    else:
-        conf.env.append_value('CFLAGS', optimization_flags)
-        conf.env.append_value('CXXFLAGS', optimization_flags)
-        conf.env.append_value('LINKFLAGS', optimization_flags)
-
     if opt.stl_debug:
-        conf.env.append_value('CXXFLAGS', "-D_GLIBCXX_DEBUG")
+        cxx_flags.append("-D_GLIBCXX_DEBUG")
 
     if conf.env['DEBUG_RT_ALLOC']:
-        conf.env.append_value('CFLAGS', '-DDEBUG_RT_ALLOC')
-        conf.env.append_value('CXXFLAGS', '-DDEBUG_RT_ALLOC')
-        conf.env.append_value('LINKFLAGS', '-ldl')
+        compiler_flags.append('-DDEBUG_RT_ALLOC')
+        linker_flags.append('-ldl')
 
     if conf.env['DEBUG_DENORMAL_EXCEPTION']:
-        conf.env.append_value('CFLAGS', '-DDEBUG_DENORMAL_EXCEPTION')
-        conf.env.append_value('CXXFLAGS', '-DDEBUG_DENORMAL_EXCEPTION')
+        compiler_flags.append('-DDEBUG_DENORMAL_EXCEPTION')
 
     if opt.universal:
         if opt.generic:
@@ -377,60 +367,53 @@ def set_compiler_flags (conf,opt):
             sys.exit (1)
         else:
             if not Options.options.nocarbon:
-                conf.env.append_value('CFLAGS', ["-arch", "i386", "-arch", "ppc"])
-                conf.env.append_value('CXXFLAGS', ["-arch", "i386", "-arch", "ppc"])
-                conf.env.append_value('LINKFLAGS', ["-arch", "i386", "-arch", "ppc"])
+                compiler_flags.extend(("-arch", "i386", "-arch", "ppc"))
+                linker_flags.extend(("-arch", "i386", "-arch", "ppc"))
             else:
-                conf.env.append_value('CFLAGS', ["-arch", "x86_64", "-arch", "i386", "-arch", "ppc"])
-                conf.env.append_value('CXXFLAGS', ["-arch", "x86_64", "-arch", "i386", "-arch", "ppc"])
-                conf.env.append_value('LINKFLAGS', ["-arch", "x86_64", "-arch", "i386", "-arch", "ppc"])
+                compiler_flags.extend(
+                        ("-arch", "x86_64", "-arch", "i386", "-arch", "ppc"))
+                linker_flags.extend(
+                        ("-arch", "x86_64", "-arch", "i386", "-arch", "ppc"))
     else:
         if opt.generic:
-            conf.env.append_value('CFLAGS', ['-arch', 'i386'])
-            conf.env.append_value('CXXFLAGS', ['-arch', 'i386'])
-            conf.env.append_value('LINKFLAGS', ['-arch', 'i386'])
+            compiler_flags.extend(('-arch', 'i386'))
+            linker_flags.extend(('-arch', 'i386'))
 
     #
     # warnings flags
     #
 
-    conf.env.append_value('CFLAGS', [ '-Wall',
-                                      '-Wpointer-arith',
-                                      '-Wcast-qual',
-                                      '-Wcast-align',
-                                      '-Wstrict-prototypes',
-                                      '-Wmissing-prototypes'
-                                      ])
-
-    conf.env.append_value('CXXFLAGS', [ '-Wall', 
-                                        '-Wpointer-arith',
-                                        '-Wcast-qual',
-                                        '-Wcast-align', 
-                                        '-Woverloaded-virtual'
-                                        ])
+    compiler_flags.extend(
+            ('-Wall', '-Wpointer-arith', '-Wcast-qual', '-Wcast-align'))
 
+    c_flags.extend(('-Wstrict-prototypes', '-Wmissing-prototypes'))
+    cxx_flags.append('-Woverloaded-virtual')
 
     #
     # more boilerplate
     #
 
-    conf.env.append_value('CFLAGS', '-DBOOST_SYSTEM_NO_DEPRECATED')
-    conf.env.append_value('CXXFLAGS', '-DBOOST_SYSTEM_NO_DEPRECATED')
-    # need ISOC9X for llabs()
-    conf.env.append_value('CFLAGS', '-D_ISOC9X_SOURCE')
-    conf.env.append_value('CFLAGS', '-D_LARGEFILE64_SOURCE')
-    conf.env.append_value('CFLAGS', '-D_FILE_OFFSET_BITS=64')
     # need ISOC9X for llabs()
-    conf.env.append_value('CXXFLAGS', '-D_ISOC9X_SOURCE')
-    conf.env.append_value('CXXFLAGS', '-D_LARGEFILE64_SOURCE')
-    conf.env.append_value('CXXFLAGS', '-D_FILE_OFFSET_BITS=64')
-
-    conf.env.append_value('CXXFLAGS', '-D__STDC_LIMIT_MACROS')
-    conf.env.append_value('CXXFLAGS', '-D__STDC_FORMAT_MACROS')
+    compiler_flags.extend(
+            ('-DBOOST_SYSTEM_NO_DEPRECATED', '-D_ISOC9X_SOURCE',
+             '-D_LARGEFILE64_SOURCE', '-D_FILE_OFFSET_BITS=64'))
+    cxx_flags.extend(('-D__STDC_LIMIT_MACROS', '-D__STDC_FORMAT_MACROS'))
 
     if opt.nls:
-        conf.env.append_value('CXXFLAGS', '-DENABLE_NLS')
-        conf.env.append_value('CFLAGS', '-DENABLE_NLS')
+        compiler_flags.append('-DENABLE_NLS')
+
+    if opt.debug:
+        conf.env.append_value('CFLAGS', debug_flags)
+        conf.env.append_value('CXXFLAGS', debug_flags)
+    else:
+        conf.env.append_value('CFLAGS', optimization_flags)
+        conf.env.append_value('CXXFLAGS', optimization_flags)
+
+    conf.env.append_value('CFLAGS', compiler_flags)
+    conf.env.append_value('CFLAGS', c_flags)
+    conf.env.append_value('CXXFLAGS', compiler_flags)
+    conf.env.append_value('CXXFLAGS', cxx_flags)
+    conf.env.append_value('LINKFLAGS', linker_flags)
 
 #----------------------------------------------------------------
 

-- 
ardour3 packaging



More information about the pkg-multimedia-commits mailing list