[SCM] ardour/master: Drop sync_cvs patch

adiknoth-guest at users.alioth.debian.org adiknoth-guest at users.alioth.debian.org
Mon Jun 25 16:07:09 UTC 2012


The following commit has been merged in the master branch:
commit f3cd8702fc578477b5051516503f0b661e8c804b
Author: Adrian Knoth <adi at drcomp.erfurt.thur.de>
Date:   Mon Jun 25 17:30:19 2012 +0200

    Drop sync_cvs patch

diff --git a/debian/patches/000_sync_vcs.patch b/debian/patches/000_sync_vcs.patch
deleted file mode 100644
index 640e1cd..0000000
--- a/debian/patches/000_sync_vcs.patch
+++ /dev/null
@@ -1,6938 +0,0 @@
-From: Adrian Knoth <adi at drcomp.erfurt.thur.de>
-Description: Sync with upstream VCS revision 9505
-Origin: git://repo.or.cz/ardour2.git
-Forwarded: Not-needed
-Last-Updated: 2011-05-17
-diff --git a/SConstruct b/SConstruct
-index 9261b40..b822c57 100644
---- a/SConstruct
-+++ b/SConstruct
-@@ -61,7 +61,7 @@ opts.AddVariables(
-     BoolVariable('GPROFILE', 'Compile with support for gprofile (Developers only)', 0),
-     BoolVariable('FREEDESKTOP', 'Install MIME type, icons and .desktop file as per the freedesktop.org spec (requires xdg-utils and shared-mime-info). "scons uninstall" removes associations in desktop database', 0),
-     BoolVariable('TRANZPORT', 'Compile with support for Frontier Designs (if libusb is available)', 1),
--    BoolVariable('AUBIO', "Use Paul Brossier's aubio library for feature detection (if available)", 1),
-+    BoolVariable('AUBIO', "Use Paul Brossier's aubio library for feature detection", 1),
-     BoolVariable('AUSTATE', "Build with support for AU settings & presets saving/loading", 0)
- )
- 
-@@ -435,7 +435,8 @@ deps = \
- 	'lrdf'                 : '0.4.0',
- 	'jack'                 : '0.109.0',
- 	'libgnomecanvas-2.0'   : '2.0',
--	'sndfile'              : '1.0.18'
-+	'sndfile'              : '1.0.18',
-+        'aubio'                : '0.3.0'
- }
- 
- def DependenciesRequiredMessage():
-@@ -499,9 +500,6 @@ if conf.CheckPKGExists ('fftw3'):
- if conf.CheckPKGExists ('aubio'):
-     libraries['aubio'] = LibraryInfo()
-     libraries['aubio'].ParseConfig('pkg-config --cflags --libs aubio')
--    env['AUBIO'] = 1
--else:
--    env['AUBIO'] = 0
- 
- env = conf.Finish ()
- 
-@@ -545,6 +543,14 @@ if env['LV2']:
- 	else:
- 		print 'LV2 support is not enabled (SLV2 not found or older than 0.6.0)'
- 		env['LV2'] = 0
-+
-+	if conf.CheckPKGVersion('rasqal', '0.9.14'):
-+		libraries['rasqal'] = LibraryInfo()
-+		libraries['rasqal'].ParseConfig('pkg-config --cflags --libs rasqal')
-+	else:
-+		print 'LV2 support is not enabled (Rasqal, required by SLV2, not found)'
-+		env['LV2'] = 0
-+
- 	conf.Finish()
- else:
- 	print 'LV2 support is not enabled.  Build with \'scons LV2=1\' to enable.'
-@@ -835,17 +841,22 @@ if env['LIBLO']:
-     env.Append(CCFLAGS="-DHAVE_LIBLO")
- 
- 
-+# It appears that SCons propagates CCFLAGS into CXXFLAGS so 
-+# we need only set these once.
- #
- # the program name is defined everywhere
- #
- env.Append(CCFLAGS='-DPROGRAM_NAME=\\"' + env['PROGRAM_NAME'] + '\\"')
--env.Append(CXXFLAGS='-DPROGRAM_NAME=\\"' + env['PROGRAM_NAME'] + '\\"')
- 
- #
- # we deal with threads and big files
- #
- env.Append(CCFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64")
--env.Append(CXXFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64")
-+
-+#
-+# we use inttypes.h format macros anywhere we want
-+#
-+env.Append(CCFLAGS="-D__STDC_FORMAT_MACROS")
- 
- #
- # fix scons nitpickiness on APPLE
-@@ -1027,6 +1038,9 @@ else:
-     print "It appears you don't have the required MIDI libraries installed. For Linux this means you are missing the development package for ALSA libraries."
-     sys.exit (1)
- 
-+pname = env['PROGRAM_NAME']
-+subst_dict['%MIDI_DEVICE_NAME%'] = pname.lower()
-+
- env = conf.Finish()
- 
- if env['GTKOSX']:
-@@ -1226,6 +1240,15 @@ timefx_subdirs = ['libs/soundtouch']
- if env['RUBBERBAND']:
-     timefx_subdirs += ['libs/rubberband']
- 
-+#
-+# Tools
-+#
-+if env['IS_OSX'] == 0 :
-+	tools_subdirs = [ 'tools/sanity_check' ]
-+else:
-+	tools_subdirs = [ ]
-+
-+
- opts.Save('scache.conf', env)
- Help(opts.GenerateHelpText(env))
- 
-@@ -1403,7 +1426,7 @@ create_stored_revision()
- for subdir in coredirs:
-     SConscript (subdir + '/SConscript')
- 
--for sublistdir in [ subdirs, timefx_subdirs, gtk_subdirs, surface_subdirs ]:
-+for sublistdir in [ subdirs, timefx_subdirs, gtk_subdirs, surface_subdirs, tools_subdirs ]:
-     for subdir in sublistdir:
-         SConscript (subdir + '/SConscript')
- 
-diff --git a/TRANSLATORS b/TRANSLATORS
-new file mode 100644
-index 0000000..b540958
---- /dev/null
-+++ b/TRANSLATORS
-@@ -0,0 +1,51 @@
-+Ardour User Interface Translation How-To
-+
-+Ardour's user interface can be translated into many languages. For this the application uses gettext engine. It works like this: there is a plain text editable PO file for every language that contains a number of sequences like: a line in English, a line in target language and a reference to a line in source code where original text in English comes from. The build system then creates a binary version of each PO file with MO file extension and places it in a system directory where running instance of Ardour will pick and use it.
-+
-+Ardour has two main PO files to translate: for user interface and for Ardour's library. Some messages from the library are actually passed to user interface (various warnings, for example), so ideally you have to translate both. For example, Russian translation is located here:
-+
-+gtk_ardour/po/ru.po
-+libs/ardour/po/ru.po
-+
-+Every PO file's name is a two-character code, e.g. de for German, es for Spanish and so on. However it's fairly common to have localizations for local versions of a language, e.g. pt_BR would stand for Brazilian Portuguese, and es_MX would stand for Mexican Spanish. Please refer to ISO language code table for details.
-+
-+Here is the best workflow for existing translations.
-+
-+1. Build Ardour  using './waf' command
-+2. Run './waf i18n'. This will update all existing translations
-+3. Open a PO file in you PO editor of choice (see below)
-+4. Open Ardour, find something untranslated, locate this phrase in PO file, translate 
-+5. Repeat previous step several times, save the PO file
-+6. In gtk_ardour/po/ run 'msgfmt -o gtk2_ardour.mo LANG.po' where LANG.po is your PO file
-+7. Run 'sudo cp gtk2_ardour.mo /usr/local/share/locale/LANG/LC_MESSAGES/' where LANG is two- or four letter code (see above)
-+8. Restart Ardour to see what your translation looks like and whether it needs fixes, e.g. has to be shorter
-+
-+When you are done, save the file and submit it to the tracker.
-+
-+There are some more things you need to know.
-+
-+1. Where does a phrase come from?
-+
-+Often when you go through translation hunting for untranslated messagesm you stumble upon things you have no idea where they come from. To assist you there most advanced PO editors have means to tell you which source code file it comes from, or, in some cases, even show the context in source code. Ardour has pretty much meaningful names for source code files, so it should help. If it doesn't, ask on IRC for help.
-+
-+2. Variables
-+
-+You will often meet things like "%1" or "%2" in translation. This is a variable that should be left intact. Here is an example:
-+
-+"Cannot load XML for session from %1"
-+
-+When Ardour runs, this "%1" will be substituted with "Ardour" so that the whole phrase will be "Cannot load XML for session from Ardour". If Mixbus runs, this will be "Cannot load XML for session from Mixbus" instead. You get the idea. So just place this variable in your translation in a way that makes the phrase sound natural in your language and make sure you know where the phrase comes from (see above) so that you know how to translate it correctly.
-+
-+3. Plural forms
-+
-+English has two plural forms, but many other languages have three and even four plural forms. Some parts of Ardour's code respect that, but some not (check for existing bug reports). A PO editor usually simplifies translating every plural form by putting every plural form into a dedicated tab.
-+
-+4. PO editors
-+
-+It's really up to you which PO editor you choose. These ones are most popular:
-+
-+poEdit. It works on Linux, Mac and Windows. The user interface is fairly simple. 
-+
-+Lokalize. Part of KDE desktop environment. It's a fairly advanced translation tool.
-+
-+GTranslator. Usually considered as GNOME translation tool, but has very few actual GNOME dependencies. Feature-wise it's someewhere between poEdit and Lokalize.
-\ No newline at end of file
-diff --git a/ardour.rc.in b/ardour.rc.in
-index bd692fa..4003c18 100644
---- a/ardour.rc.in
-+++ b/ardour.rc.in
-@@ -1,8 +1,8 @@
- <?xml version="1.0" encoding="UTF-8"?>
- <Ardour>
--  <MIDI-port tag="%MIDITAG%" device="ardour" type="%MIDITYPE%" mode="duplex"/>
--  <MIDI-port tag="control" device="ardour" type="%MIDITYPE%" mode="duplex"/>
--  <MIDI-port tag="mcu" device="ardour" type="%MIDITYPE%" mode="duplex"/>
-+  <MIDI-port tag="%MIDITAG%" device="%MIDI_DEVICE_NAME%" type="%MIDITYPE%" mode="duplex"/>
-+  <MIDI-port tag="control" device="%MIDI_DEVICE_NAME%" type="%MIDITYPE%" mode="duplex"/>
-+  <MIDI-port tag="mcu" device="%MIDI_DEVICE_NAME%" type="%MIDITYPE%" mode="duplex"/>
-   <Config>
-     <Option name="minimum-disk-io-bytes" value="262144"/>
-     <Option name="track-buffer-seconds" value="5.000000"/>
-diff --git a/gtk2_ardour/SAE-de-keypad.bindings.in b/gtk2_ardour/SAE-de-keypad.bindings.in
-index dad2ead..d22509f 100644
---- a/gtk2_ardour/SAE-de-keypad.bindings.in
-+++ b/gtk2_ardour/SAE-de-keypad.bindings.in
-@@ -119,7 +119,8 @@
- 
- (gtk_accel_path "<Actions>/Editor/playhead-to-edit" "Return")
- (gtk_accel_path "<Actions>/Editor/edit-to-playhead" "<%SECONDARY%>Return")
--(gtk_accel_path "<Actions>/Editor/editor-delete" "BackSpace")
-+(gtk_accel_path "<Actions>/Editor/editor-delete" "Delete")
-+(gtk_accel_path "<Actions>/Editor/editor-alternate-delete" "BackSpace")
- (gtk_accel_path "<Actions>/Editor/remove-last-capture" "<%PRIMARY%>Delete")
- 
- (gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-boundary-noselection" "<%LEVEL4%>leftarrow")
-diff --git a/gtk2_ardour/SAE-de-nokeypad.bindings.in b/gtk2_ardour/SAE-de-nokeypad.bindings.in
-index bcd7f6d..61af30e 100644
---- a/gtk2_ardour/SAE-de-nokeypad.bindings.in
-+++ b/gtk2_ardour/SAE-de-nokeypad.bindings.in
-@@ -118,7 +118,8 @@
- 
- (gtk_accel_path "<Actions>/Editor/playhead-to-edit" "Return")
- (gtk_accel_path "<Actions>/Editor/edit-to-playhead" "<%SECONDARY%>Return")
--(gtk_accel_path "<Actions>/Editor/editor-delete" "BackSpace")
-+(gtk_accel_path "<Actions>/Editor/editor-delete" "Delete")
-+(gtk_accel_path "<Actions>/Editor/editor-alternate-delete" "BackSpace")
- (gtk_accel_path "<Actions>/Editor/remove-last-capture" "<%PRIMARY%>BackSpace")
- 
- (gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-boundary-noselection" "<%LEVEL4%>leftarrow")
-diff --git a/gtk2_ardour/SAE-us-keypad.bindings.in b/gtk2_ardour/SAE-us-keypad.bindings.in
-index 88085b0..9b5d6c7 100644
---- a/gtk2_ardour/SAE-us-keypad.bindings.in
-+++ b/gtk2_ardour/SAE-us-keypad.bindings.in
-@@ -117,7 +117,8 @@
- 
- (gtk_accel_path "<Actions>/Editor/playhead-to-edit" "Return")
- (gtk_accel_path "<Actions>/Editor/edit-to-playhead" "<%SECONDARY%>Return")
--(gtk_accel_path "<Actions>/Editor/editor-delete" "BackSpace")
-+(gtk_accel_path "<Actions>/Editor/editor-delete" "Delete")
-+(gtk_accel_path "<Actions>/Editor/editor-alternate-delete" "BackSpace")
- (gtk_accel_path "<Actions>/Editor/remove-last-capture" "<%PRIMARY%>Delete")
- 
- (gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-boundary-noselection" "<%LEVEL4%>leftarrow")
-diff --git a/gtk2_ardour/SAE-us-nokeypad.bindings.in b/gtk2_ardour/SAE-us-nokeypad.bindings.in
-index 33fe2f0..fe41b7d 100644
---- a/gtk2_ardour/SAE-us-nokeypad.bindings.in
-+++ b/gtk2_ardour/SAE-us-nokeypad.bindings.in
-@@ -116,7 +116,8 @@
- 
- (gtk_accel_path "<Actions>/Editor/playhead-to-edit" "Return")
- (gtk_accel_path "<Actions>/Editor/edit-to-playhead" "<%SECONDARY%>Return")
--(gtk_accel_path "<Actions>/Editor/editor-delete" "BackSpace")
-+(gtk_accel_path "<Actions>/Editor/editor-delete" "Delete")
-+(gtk_accel_path "<Actions>/Editor/editor-alternate-delete" "BackSpace")
- (gtk_accel_path "<Actions>/Editor/remove-last-capture" "<%PRIMARY%>BackSpace")
- 
- (gtk_accel_path "<Actions>/Editor/playhead-to-previous-region-boundary-noselection" "<%LEVEL4%>leftarrow")
-diff --git a/gtk2_ardour/SConscript b/gtk2_ardour/SConscript
-index 2ebbe8b..ada7907 100644
---- a/gtk2_ardour/SConscript
-+++ b/gtk2_ardour/SConscript
-@@ -291,6 +291,7 @@ if env['LV2']:
- 	extra_sources += lv2_files
- 	gtkardour.Append (CCFLAGS="-DHAVE_LV2")
- 	gtkardour.Merge ([libraries['slv2']])
-+	gtkardour.Merge ([libraries['rasqal']])
- 
- 
- if gtkardour['GTKOSX']:
-diff --git a/gtk2_ardour/analysis_window.cc b/gtk2_ardour/analysis_window.cc
-index e877de5..0c9db7c 100644
---- a/gtk2_ardour/analysis_window.cc
-+++ b/gtk2_ardour/analysis_window.cc
-@@ -87,7 +87,7 @@ AnalysisWindow::AnalysisWindow() :
- 
- 
- 	// "Signal source"
--	vbox.pack_start(source_selection_label, false, false);
-+	//vbox.pack_start(source_selection_label, false, false);
- 
- 	{
- 		Gtk::RadioButtonGroup group = source_selection_ranges_rb.get_group();
-@@ -95,8 +95,8 @@ AnalysisWindow::AnalysisWindow() :
- 
- 		source_selection_ranges_rb.set_active();
- 		
--		vbox.pack_start (source_selection_ranges_rb,  false, false);
--		vbox.pack_start (source_selection_regions_rb, false, false);
-+		//vbox.pack_start (source_selection_ranges_rb,  false, false);
-+		//vbox.pack_start (source_selection_regions_rb, false, false);
- 		
- 		// "Selected ranges" radio
- 		source_selection_ranges_rb.signal_toggled().connect (
-@@ -107,18 +107,18 @@ AnalysisWindow::AnalysisWindow() :
- 				bind ( mem_fun(*this, &AnalysisWindow::source_selection_changed), &source_selection_regions_rb));
- 	}
- 	
--	vbox.pack_start(hseparator1, false, false);
-+	//vbox.pack_start(hseparator1, false, false);
- 	
- 	// "Display model"
--	vbox.pack_start(display_model_label, false, false);
-+	//vbox.pack_start(display_model_label, false, false);
- 	{
- 		Gtk::RadioButtonGroup group = display_model_composite_separate_rb.get_group();
- 		display_model_composite_all_tracks_rb.set_group (group);
- 		
- 		display_model_composite_separate_rb.set_active();
- 		
--		vbox.pack_start (display_model_composite_separate_rb,   false, false);
--		vbox.pack_start (display_model_composite_all_tracks_rb, false, false);
-+		//vbox.pack_start (display_model_composite_separate_rb,   false, false);
-+		//vbox.pack_start (display_model_composite_all_tracks_rb, false, false);
- 
- 		// "Composite graphs for all tracks"
- 		display_model_composite_separate_rb.signal_toggled().connect (
-@@ -136,7 +136,7 @@ AnalysisWindow::AnalysisWindow() :
- 
- 	refresh_button.signal_clicked().connect ( bind ( mem_fun(*this, &AnalysisWindow::analyze_data), &refresh_button)); 
- 
--	vbox.pack_start(refresh_button, false, false, 10);
-+	vbox.pack_start(refresh_button, false, false);
- 
- 
- 	// Feature checkboxes
-@@ -147,7 +147,7 @@ AnalysisWindow::AnalysisWindow() :
- 
- 	// normalize
- 	show_normalized_button.signal_toggled().connect( mem_fun(*this, &AnalysisWindow::show_normalized_changed));
--	vbox.pack_start(show_normalized_button, false, false);
-+	//vbox.pack_start(show_normalized_button, false, false);
- 
- 	
- 
-diff --git a/gtk2_ardour/ardev_common.sh.in b/gtk2_ardour/ardev_common.sh.in
-index f27da66..b2c6a51 100644
---- a/gtk2_ardour/ardev_common.sh.in
-+++ b/gtk2_ardour/ardev_common.sh.in
-@@ -11,9 +11,9 @@ else
-     echo USING OLD CLEARLOOKS
-     export GTK_PATH=~/.ardour2:libs/clearlooks-older
- fi
--export VAMP_PATH=libs/vamp-plugins:$VAMP_PATH
-+export VAMP_PATH=libs/vamp-plugins${VAMP_PATH:+:$VAMP_PATH}
- 
--export LD_LIBRARY_PATH=libs/vamp-sdk:libs/surfaces/control_protocol:libs/ardour:libs/midi++2:libs/pbd:libs/rubberband:libs/soundtouch:libs/gtkmm2ext:libs/sigc++2:libs/glibmm2:libs/gtkmm2/atk:libs/gtkmm2/pango:libs/gtkmm2/gdk:libs/gtkmm2/gtk:libs/libgnomecanvasmm:libs/libsndfile:libs/appleutility:$LD_LIBRARY_PATH
-+export LD_LIBRARY_PATH=libs/vamp-sdk:libs/surfaces/control_protocol:libs/ardour:libs/midi++2:libs/pbd:libs/rubberband:libs/soundtouch:libs/gtkmm2ext:libs/sigc++2:libs/glibmm2:libs/gtkmm2/atk:libs/gtkmm2/pango:libs/gtkmm2/gdk:libs/gtkmm2/gtk:libs/libgnomecanvasmm:libs/libsndfile:libs/appleutility${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
- 
- # DYLD_LIBRARY_PATH is for darwin.
- export DYLD_FALLBACK_LIBRARY_PATH=$LD_LIBRARY_PATH
-diff --git a/gtk2_ardour/ardour.menus.in b/gtk2_ardour/ardour.menus.in
-index 9200c0b..8830ae4 100644
---- a/gtk2_ardour/ardour.menus.in
-+++ b/gtk2_ardour/ardour.menus.in
-@@ -1,5 +1,7 @@
- <ui>
- 
-+     <accelerator action='editor-alternate-delete'/>
-+     
-     <menubar name='Main' action='MainMenu'>
-         <menu name='Session' action='Session'>
-            <menuitem action='New'/>
-diff --git a/gtk2_ardour/ardour.sh.in b/gtk2_ardour/ardour.sh.in
-index e1a0bd6..8e9d09d 100644
---- a/gtk2_ardour/ardour.sh.in
-+++ b/gtk2_ardour/ardour.sh.in
-@@ -1,8 +1,8 @@
- #!/bin/sh
- 
--export GTK_PATH=%INSTALL_PREFIX%/%LIBDIR%/ardour2:$GTK_PATH
-+export GTK_PATH=%INSTALL_PREFIX%/%LIBDIR%/ardour2${GTK_PATH:+:$GTK_PATH}
- 
--export LD_LIBRARY_PATH=%INSTALL_PREFIX%/%LIBDIR%/ardour2:$LD_LIBRARY_PATH 
-+export LD_LIBRARY_PATH=%INSTALL_PREFIX%/%LIBDIR%/ardour2${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
- # DYLD_LIBRARY_PATH is for Darwin
- export DYLD_LIBRARY_PATH=$LD_LIBRARY_PATH
- 
-diff --git a/gtk2_ardour/ardour_ui.cc b/gtk2_ardour/ardour_ui.cc
-index cd0504f..c309812 100644
---- a/gtk2_ardour/ardour_ui.cc
-+++ b/gtk2_ardour/ardour_ui.cc
-@@ -34,6 +34,7 @@
- 
- #include <gtkmm/messagedialog.h>
- #include <gtkmm/accelmap.h>
-+#include <gtkmm2ext/application.h>
- 
- #include <pbd/error.h>
- #include <pbd/basename.h>
-@@ -643,6 +644,11 @@ Please consider the possibilities, and perhaps (re)start JACK."));
- void
- ARDOUR_UI::startup ()
- {
-+	Application* app = Application::instance();
-+
-+	app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
-+	app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_load));
-+
- 	string name, path;
- 	
- 	new_session_dialog = new NewSessionDialog();
-@@ -653,7 +659,9 @@ ARDOUR_UI::startup ()
- 	if (audio_setup) {
- 		new_session_dialog->engine_control.set_state (*audio_setup);
- 	}
--	
-+
-+	app->ready ();
-+
- 	if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
- 		return;
- 	}
-@@ -2347,6 +2355,7 @@ void
- ARDOUR_UI::idle_load (const Glib::ustring& path)
- {
- 	if (session) {
-+
- 		if (Glib::file_test (path, Glib::FILE_TEST_IS_DIR)) {
- 			/* /path/to/foo => /path/to/foo, foo */
- 			load_session (path, basename_nosuffix (path));
-@@ -2354,13 +2363,13 @@ ARDOUR_UI::idle_load (const Glib::ustring& path)
- 			/* /path/to/foo/foo.ardour => /path/to/foo, foo */
- 			load_session (Glib::path_get_dirname (path), basename_nosuffix (path));
- 		}
-+
- 	} else {
- 
- 		ARDOUR_COMMAND_LINE::session_name = path;
- 
- 		if (new_session_dialog) {
- 
--
- 			/* make it break out of Dialog::run() and
- 			   start again.
- 			 */
-diff --git a/gtk2_ardour/ardour_ui_ed.cc b/gtk2_ardour/ardour_ui_ed.cc
-index bbf3dbb..4e6121b 100644
---- a/gtk2_ardour/ardour_ui_ed.cc
-+++ b/gtk2_ardour/ardour_ui_ed.cc
-@@ -891,9 +891,6 @@ ARDOUR_UI::use_menubar_as_top_menubar ()
- 	}
- 
- 	app->set_menu_bar (*menu_bar);
--
--	app->ShouldQuit.connect (sigc::mem_fun (*this, &ARDOUR_UI::queue_finish));
--	app->ShouldLoad.connect (sigc::mem_fun (*this, &ARDOUR_UI::idle_load));
- }
- 
- void
-diff --git a/gtk2_ardour/au_pluginui.mm b/gtk2_ardour/au_pluginui.mm
-index 66a6602..a704dcd 100644
---- a/gtk2_ardour/au_pluginui.mm
-+++ b/gtk2_ardour/au_pluginui.mm
-@@ -120,7 +120,7 @@ AUPluginUI::AUPluginUI (boost::shared_ptr<PluginInsert> insert)
- 		error << _("unknown type of editor-supplying plugin (note: no AudioUnit support in this version of ardour)") << endmsg;
- 		throw failed_constructor ();
- 	}
--
-+	
- 	/* stuff some stuff into the top of the window */
- 
- 	HBox* smaller_hbox = manage (new HBox);
-@@ -171,8 +171,10 @@ AUPluginUI::AUPluginUI (boost::shared_ptr<PluginInsert> insert)
- 	/* prefer cocoa, fall back to cocoa, but use carbon if its there */
- 
- 	if (test_cocoa_view_support()) {
-+	        cerr << insert->name() << " creating cocoa view\n";
- 		create_cocoa_view ();
- 	} else if (test_carbon_view_support()) {
-+	        cerr << insert->name() << " creating carbon view\n";
- 		create_carbon_view ();
- 	} else {
- 		create_cocoa_view ();
-@@ -268,11 +270,11 @@ AUPluginUI::create_cocoa_view ()
- {
- 	BOOL wasAbleToLoadCustomView = NO;
- 	AudioUnitCocoaViewInfo* cocoaViewInfo = NULL;
--	UInt32               numberOfClasses = 0;
-+	UInt32     numberOfClasses = 0;
- 	UInt32     dataSize;
- 	Boolean    isWritable;
--	NSString*	    factoryClassName = 0;
--	NSURL*	            CocoaViewBundlePath;
-+	NSString*  factoryClassName = 0;
-+	NSURL*     CocoaViewBundlePath = 0;
- 
- 	OSStatus result = AudioUnitGetPropertyInfo (*au->get_au(),
- 						    kAudioUnitProperty_CocoaUI,
-@@ -286,7 +288,9 @@ AUPluginUI::create_cocoa_view ()
- 	// Does view have custom Cocoa UI?
- 	
- 	if ((result == noErr) && (numberOfClasses > 0) ) {
-+		cerr << insert->name() << " has " << numberOfClasses << " cocoa UI classes\n";
- 		cocoaViewInfo = (AudioUnitCocoaViewInfo *)malloc(dataSize);
-+
- 		if(AudioUnitGetProperty(*au->get_au(),
- 					kAudioUnitProperty_CocoaUI,
- 					kAudioUnitScope_Global,
-@@ -298,6 +302,7 @@ AUPluginUI::create_cocoa_view ()
- 			
- 			// we only take the first view in this example.
- 			factoryClassName	= (NSString *)cocoaViewInfo->mCocoaAUViewClass[0];
-+	                cerr << insert->name() << " fetching cocoa UI via factory called " << factoryClassName << '\n';
- 
- 		} else {
- 
-@@ -523,7 +528,6 @@ int
- AUPluginUI::parent_cocoa_window ()
- {
- 	NSWindow* win = get_nswindow ();
--	NSRect packFrame;
- 
- 	if (!win) {
- 		return -1;
-diff --git a/gtk2_ardour/audio_streamview.cc b/gtk2_ardour/audio_streamview.cc
-index 8d12fef..6e53ae8 100644
---- a/gtk2_ardour/audio_streamview.cc
-+++ b/gtk2_ardour/audio_streamview.cc
-@@ -378,6 +378,8 @@ AudioStreamView::redisplay_diskstream ()
- 	list<RegionView *>::iterator i, tmp;
- 	list<CrossfadeView*>::iterator xi, tmpx;
- 
-+//        cerr << "REDISPLAY diskstream\n";
-+
- 	for (i = region_views.begin(); i != region_views.end(); ++i) {
- 		(*i)->set_valid (false);
- 	}
-@@ -424,6 +426,7 @@ AudioStreamView::redisplay_diskstream ()
- 	/* now fix layering */
- 
- 	for (RegionViewList::iterator i = region_views.begin(); i != region_views.end(); ++i) {
-+//                cerr << "Layering call for " << (*i)->region()->name() << endl;
- 		region_layered (*i);
- 	}
- }
-diff --git a/gtk2_ardour/automation_line.cc b/gtk2_ardour/automation_line.cc
-index 7fb88d6..54620cd 100644
---- a/gtk2_ardour/automation_line.cc
-+++ b/gtk2_ardour/automation_line.cc
-@@ -564,7 +564,7 @@ AutomationLine::determine_visible_control_points (ALPoints& points)
- 	uint32_t prev_rx = 0;
- 	uint32_t this_ry = 0;
-  	uint32_t prev_ry = 0;	
--	double* slope;
-+	double* slope = NULL;
- 	uint32_t box_size;
- 	uint32_t cpsize;
- 
-@@ -587,13 +587,13 @@ AutomationLine::determine_visible_control_points (ALPoints& points)
- 
- 	/* compute derivative/slope for the entire line */
- 
--	slope = new double[npoints];
-+	//slope = new double[npoints];
- 
--	for (n = 0; n < npoints - 1; ++n) {
--		double xdelta = points[n+1].x - points[n].x;
--		double ydelta = points[n+1].y - points[n].y;
--		slope[n] = ydelta/xdelta;
--	}
-+	//for (n = 0; n < npoints - 1; ++n) {
-+	//	double xdelta = points[n+1].x - points[n].x;
-+	//	double ydelta = points[n+1].y - points[n].y;
-+	//	slope[n] = ydelta/xdelta;
-+	//}
- 
- 	box_size = (uint32_t) control_point_box_size ();
- 
-@@ -626,14 +626,14 @@ AutomationLine::determine_visible_control_points (ALPoints& points)
- 			continue;
- 		}
- 
--		if (pi > 0 && pi < npoints - 1) {
--			if (slope[pi] == slope[pi-1]) {
-+//		if (pi > 0 && pi < npoints - 1) {
-+//			if (slope[pi] == slope[pi-1]) {
- 
- 				/* no reason to display this point */
- 				
--				continue;
--			}
--		}
-+//				continue;
-+//			}
-+//		}
- 		
- 		/* need to round here. the ultimate coordinates are integer
- 		   pixels, so tiny deltas in the coords will be eliminated
-@@ -646,12 +646,12 @@ AutomationLine::determine_visible_control_points (ALPoints& points)
- 		this_rx = (uint32_t) rint (tx);
-       		this_ry = (uint32_t) rint (ty); 
-  
-- 		if (view_index && pi != npoints && /* not the first, not the last */
--		    (((this_rx == prev_rx) && (this_ry == prev_ry)) || /* same point */
--		     (((this_rx - prev_rx) < (box_size + 2)) &&  /* not identical, but still too close horizontally */
--		      (abs ((int)(this_ry - prev_ry)) < (int) (box_size + 2))))) { /* too close vertically */
--  			continue;
--		} 
-+ //		if (view_index && pi != npoints && /* not the first, not the last */
-+//		    (((this_rx == prev_rx) && (this_ry == prev_ry)) || /* same point */
-+//		     (((this_rx - prev_rx) < (box_size + 2)) &&  /* not identical, but still too close horizontally */
-+//		      (abs ((int)(this_ry - prev_ry)) < (int) (box_size + 2))))) { /* too close vertically */
-+//  			continue;
-+//		} 
- 
- 		/* ok, we should display this point */
- 
-diff --git a/gtk2_ardour/canvas-waveview.c b/gtk2_ardour/canvas-waveview.c
-index 29cc850..750d135 100644
---- a/gtk2_ardour/canvas-waveview.c
-+++ b/gtk2_ardour/canvas-waveview.c
-@@ -1246,12 +1246,12 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
- 		max = waveview->cache->data[cache_index].max;
- 		min = waveview->cache->data[cache_index].min;
- 		
--		if (max >= 1.0) {
-+		if (max >= 0.98853) { // -0.9dBFS
- 			max = 1.0;
- 			next_clip_max = 1;
- 		}
- 		
--		if (min <= -1.0) {
-+		if (min <= -0.98853) { // ditto
- 			min = -1.0;
- 			next_clip_min = 1;
- 		}
-diff --git a/gtk2_ardour/editor.cc b/gtk2_ardour/editor.cc
-index d6dcfc9..79e71b5 100644
---- a/gtk2_ardour/editor.cc
-+++ b/gtk2_ardour/editor.cc
-@@ -1892,7 +1892,7 @@ Editor::add_region_context_items (AudioStreamView* sv, boost::shared_ptr<Region>
- 	items.push_back (MenuElem (_("Bounce"), mem_fun(*this, &Editor::bounce_region_selection)));
- 
- #ifdef FFT_ANALYSIS
--	items.push_back (MenuElem (_("Spectral Analysis"), mem_fun(*this, &Editor::analyze_region_selection)));
-+//	items.push_back (MenuElem (_("Spectral Analysis"), mem_fun(*this, &Editor::analyze_region_selection)));
- #endif
- 
- 	items.push_back (SeparatorElem());
-@@ -2088,6 +2088,10 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& items)
- 	items.push_back (MenuElem (_("Play range"), mem_fun(*this, &Editor::play_selection)));
- 	items.push_back (MenuElem (_("Loop range"), bind (mem_fun(*this, &Editor::set_loop_from_selection), true)));
- 
-+	items.push_back (SeparatorElem());
-+	items.push_back (MenuElem (_("Set loop from selection"), bind (mem_fun(*this, &Editor::set_loop_from_selection), false)));
-+	items.push_back (MenuElem (_("Set punch from selection"), mem_fun(*this, &Editor::set_punch_from_selection)));
-+
- #ifdef FFT_ANALYSIS
- 	items.push_back (SeparatorElem());
- 	items.push_back (MenuElem (_("Spectral Analysis"), mem_fun(*this, &Editor::analyze_range_selection)));
-@@ -2105,10 +2109,6 @@ Editor::add_selection_context_items (Menu_Helpers::MenuList& items)
- 	items.push_back (MenuElem (_("Select all in range"), mem_fun(*this, &Editor::select_all_selectables_using_time_selection)));
- 
- 	items.push_back (SeparatorElem());
--	items.push_back (MenuElem (_("Set loop from selection"), bind (mem_fun(*this, &Editor::set_loop_from_selection), false)));
--	items.push_back (MenuElem (_("Set punch from selection"), mem_fun(*this, &Editor::set_punch_from_selection)));
--	
--	items.push_back (SeparatorElem());
- 	items.push_back (MenuElem (_("Add Range Markers"), mem_fun (*this, &Editor::add_location_from_selection)));
- 	items.push_back (SeparatorElem());
- 	items.push_back (MenuElem (_("Crop region to range"), mem_fun(*this, &Editor::crop_region_to_selection)));
-diff --git a/gtk2_ardour/editor.h b/gtk2_ardour/editor.h
-index 992ac59..3d1feee 100644
---- a/gtk2_ardour/editor.h
-+++ b/gtk2_ardour/editor.h
-@@ -330,10 +330,6 @@ class Editor : public PublicEditor
- 	void toggle_measure_visibility ();
- 	void toggle_logo_visibility ();
- 
--	double get_physical_screen_width () const { return physical_screen_width; };
--	double physical_screen_width;
--	double physical_screen_height;
--
- 	/* SMPTE timecode & video sync */
- 
- 	void smpte_fps_chosen (ARDOUR::SmpteFormat format);
-diff --git a/gtk2_ardour/editor_actions.cc b/gtk2_ardour/editor_actions.cc
-index 89136db..c11cbe0 100644
---- a/gtk2_ardour/editor_actions.cc
-+++ b/gtk2_ardour/editor_actions.cc
-@@ -553,6 +553,8 @@ Editor::register_actions ()
- 	/* Note: for now, editor-delete does the exact same thing as editor-cut */
- 	act = ActionManager::register_action (editor_actions, "editor-delete", _("Delete"), mem_fun(*this, &Editor::cut));
- 	ActionManager::session_sensitive_actions.push_back (act);
-+	act = ActionManager::register_action (editor_actions, "editor-alternate-delete", _("Delete (Backspace)"), mem_fun(*this, &Editor::cut));
-+	ActionManager::session_sensitive_actions.push_back (act);
- 	act = ActionManager::register_action (editor_actions, "editor-copy", _("Copy"), mem_fun(*this, &Editor::copy));
- 	ActionManager::session_sensitive_actions.push_back (act);
- 	act = ActionManager::register_action (editor_actions, "editor-paste", _("Paste"), mem_fun(*this, &Editor::keyboard_paste));
-diff --git a/gtk2_ardour/editor_audio_import.cc b/gtk2_ardour/editor_audio_import.cc
-index 4f1a63b..bcbe3eb 100644
---- a/gtk2_ardour/editor_audio_import.cc
-+++ b/gtk2_ardour/editor_audio_import.cc
-@@ -164,7 +164,9 @@ Editor::external_audio_dialog ()
- 		}
- 
- 		SrcQuality quality = sfbrowser->get_src_quality();
-+                
- 
-+                cerr << "Start import of " << paths.size() << " at " << where << endl;
- 
- 		if (sfbrowser->copy_files_btn.get_active()) {
- 			do_import (paths, chns, mode, quality, where);
-@@ -289,6 +291,7 @@ Editor::do_import (vector<ustring> paths, ImportDisposition chns, ImportMode mod
- 	boost::shared_ptr<AudioTrack> track;
- 	vector<ustring> to_import;
- 	int nth = 0;
-+        bool use_timestamp = (pos == -1);
- 
- 	if (interthread_progress_window == 0) {
- 		build_interthread_progress_window ();
-@@ -339,6 +342,11 @@ Editor::do_import (vector<ustring> paths, ImportDisposition chns, ImportMode mod
- 				/* NOTREACHED*/
- 			}
- 
-+                        /* have to reset this for every file we handle */
-+
-+                        if (use_timestamp) {
-+                                pos = -1;
-+                        }
- 
- 			switch (chns) {
- 			case Editing::ImportDistinctFiles:
-@@ -682,14 +690,6 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64
- 	
- 	use_timestamp = (pos == -1);
- 
--	if (use_timestamp) {
--		if (sources[0]->natural_position() != 0) {
--			pos = sources[0]->natural_position();
--		} else {
--			pos = get_preferred_edit_position ();
--		}
--	}
--
- 	if (target_regions == 1) {
- 
- 		/* take all the sources we have and package them up as a region */
-@@ -699,8 +699,8 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64
- 				   (RegionFactory::create (sources, 0, sources[0]->length(), region_name, 0,
- 							   Region::Flag (Region::DefaultFlags|Region::WholeFile|Region::External)));
- 							   
--        if (use_timestamp) {
--		    ar->special_set_position(sources[0]->natural_position());
-+                if (use_timestamp) {
-+                        ar->special_set_position(sources[0]->natural_position());
- 		}
- 		
- 		regions.push_back (ar);
-@@ -750,16 +750,57 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64
- 	}
- 
- 	int n = 0;
-+        nframes_t rlen = 0;
-+
-+        cerr << "About to add " << regions.size() << endl;
- 
-         for (vector<boost::shared_ptr<AudioRegion> >::iterator r = regions.begin(); r != regions.end(); ++r, ++n) {
--                
-+
-+                if (use_timestamp) {
-+                        
-+                        cerr << "Using timestamp to place region " << (*r)->name() << endl;
-+
-+                        /* get timestamp for this region */
-+
-+                        const boost::shared_ptr<Source> s ((*r)->get_sources().front());
-+                        const boost::shared_ptr<AudioSource> as = boost::dynamic_pointer_cast<AudioSource> (s);
-+                        
-+                        assert (as);
-+                        
-+                        if (as->natural_position() != 0) {
-+                                pos = as->natural_position();
-+                                cerr << "\tgot " << pos << " from source TC info\n";
-+                        } else if (target_tracks == 1) {
-+                                /* hmm, no timestamp available, put it after the previous region
-+                                 */
-+                                if (n == 0) {
-+                                        pos = get_preferred_edit_position ();
-+                                        cerr << "\tno timestamp, first file, use edit pos = " << pos << endl;
-+                                } else {
-+                                        pos += rlen;
-+                                        cerr << "\tpacked-sequence-shuffle to " << pos << endl;
-+                                }
-+                        } else {
-+                                pos = get_preferred_edit_position ();
-+                                cerr << "\tmultitracks, using edit position = " << pos << endl;
-+                        }
-+                                
-+                }
-+
-+                cerr << "Actually inserting at " << pos << endl;
-+
-                 finish_bringing_in_audio (*r, input_chan, output_chan, pos, mode, track);
- 
-+                rlen = (*r)->length();
-+
-                 if (target_tracks != 1) {
-                         track.reset ();
--		} else {
--			pos += (*r)->length();
--		} 
-+                } else { 
-+                        if (!use_timestamp) {
-+                                /* line each one up right after the other */
-+                                pos += (*r)->length();
-+                        }
-+                }
- 	}
- 
- 	/* setup peak file building in another thread */
-diff --git a/gtk2_ardour/editor_canvas.cc b/gtk2_ardour/editor_canvas.cc
-index a029c65..1c7e7bf 100644
---- a/gtk2_ardour/editor_canvas.cc
-+++ b/gtk2_ardour/editor_canvas.cc
-@@ -107,13 +107,8 @@ Editor::initialize_canvas ()
- 	track_canvas->set_center_scroll_region (false);
- 	track_canvas->set_dither (Gdk::RGB_DITHER_NONE);
- 
--	Glib::RefPtr<Gdk::Screen> screen = get_screen();
--
--	if (!screen) {
--		screen = Gdk::Screen::get_default();
--	}
--	physical_screen_width = screen->get_width ();
--	physical_screen_height = screen->get_height ();
-+	gint phys_width = physical_screen_width (Glib::RefPtr<Gdk::Window>());
-+	gint phys_height = physical_screen_height (Glib::RefPtr<Gdk::Window>());
- 
- 	/* stuff for the verbose canvas cursor */
- 
-@@ -144,21 +139,21 @@ Editor::initialize_canvas ()
- 
- #ifdef GTKOSX
- 	/*XXX please don't laugh. this actually improves canvas performance on osx */
--	bogus_background_rect =  new ArdourCanvas::SimpleRect (*time_line_group, 0.0, 0.0, max_canvas_coordinate/3, physical_screen_height);
-+	bogus_background_rect =  new ArdourCanvas::SimpleRect (*time_line_group, 0.0, 0.0, max_canvas_coordinate/3, phys_height);
- 	bogus_background_rect->property_outline_pixels() = 0;
- #endif
--	transport_loop_range_rect = new ArdourCanvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, physical_screen_height);
-+	transport_loop_range_rect = new ArdourCanvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, phys_height);
- 	transport_loop_range_rect->property_outline_pixels() = 1;
- 	transport_loop_range_rect->hide();
- 
--	transport_punch_range_rect = new ArdourCanvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, physical_screen_height);
-+	transport_punch_range_rect = new ArdourCanvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, phys_height);
- 	transport_punch_range_rect->property_outline_pixels() = 0;
- 	transport_punch_range_rect->hide();
- 
- 	_background_group = new ArdourCanvas::Group (*track_canvas->root());
- 	_master_group = new ArdourCanvas::Group (*track_canvas->root());
- 
--	range_marker_drag_rect = new ArdourCanvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, physical_screen_height);
-+	range_marker_drag_rect = new ArdourCanvas::SimpleRect (*time_line_group, 0.0, 0.0, 0.0, phys_height);
- 	range_marker_drag_rect->hide ();
- 
- 	_trackview_group = new ArdourCanvas::Group (*_master_group);
-@@ -166,60 +161,60 @@ Editor::initialize_canvas ()
- 
- 	meter_bar_group = new ArdourCanvas::Group (*track_canvas->root ());
- 	if (Profile->get_sae()) {
--		meter_bar = new ArdourCanvas::SimpleRect (*meter_bar_group, 0.0, 0.0, physical_screen_width, timebar_height - 1);
-+		meter_bar = new ArdourCanvas::SimpleRect (*meter_bar_group, 0.0, 0.0, phys_width, timebar_height - 1);
- 		meter_bar->property_outline_pixels() = 1;
- 	} else {
--		meter_bar = new ArdourCanvas::SimpleRect (*meter_bar_group, 0.0, 0.0, physical_screen_width, timebar_height);
-+		meter_bar = new ArdourCanvas::SimpleRect (*meter_bar_group, 0.0, 0.0, phys_width, timebar_height);
- 		meter_bar->property_outline_pixels() = 0;
- 	}
- 	meter_bar->property_outline_what() = (0x1 | 0x8);
- 
- 	tempo_bar_group = new ArdourCanvas::Group (*track_canvas->root ());
- 	if (Profile->get_sae()) {
--		tempo_bar = new ArdourCanvas::SimpleRect (*tempo_bar_group, 0.0, 0.0, physical_screen_width, (timebar_height - 1));
-+		tempo_bar = new ArdourCanvas::SimpleRect (*tempo_bar_group, 0.0, 0.0, phys_width, (timebar_height - 1));
- 		tempo_bar->property_outline_pixels() = 1;
- 	} else {
--		tempo_bar = new ArdourCanvas::SimpleRect (*tempo_bar_group, 0.0, 0.0, physical_screen_width, (timebar_height));
-+		tempo_bar = new ArdourCanvas::SimpleRect (*tempo_bar_group, 0.0, 0.0, phys_width, (timebar_height));
- 		tempo_bar->property_outline_pixels() = 0;
- 	}
- 	tempo_bar->property_outline_what() = (0x1 | 0x8);
- 
- 	range_marker_bar_group = new ArdourCanvas::Group (*track_canvas->root ());
- 	if (Profile->get_sae()) {
--		range_marker_bar = new ArdourCanvas::SimpleRect (*range_marker_bar_group, 0.0, 0.0, physical_screen_width, (timebar_height - 1));
-+		range_marker_bar = new ArdourCanvas::SimpleRect (*range_marker_bar_group, 0.0, 0.0, phys_width, (timebar_height - 1));
- 		range_marker_bar->property_outline_pixels() = 1;
- 	} else {
--		range_marker_bar = new ArdourCanvas::SimpleRect (*range_marker_bar_group, 0.0, 0.0, physical_screen_width, (timebar_height));
-+		range_marker_bar = new ArdourCanvas::SimpleRect (*range_marker_bar_group, 0.0, 0.0, phys_width, (timebar_height));
- 		range_marker_bar->property_outline_pixels() = 0;
- 	}
- 	range_marker_bar->property_outline_what() = (0x1 | 0x8);
- 	
- 	transport_marker_bar_group = new ArdourCanvas::Group (*track_canvas->root ());
- 	if (Profile->get_sae()) {
--		transport_marker_bar = new ArdourCanvas::SimpleRect (*transport_marker_bar_group, 0.0, 0.0,  physical_screen_width, (timebar_height - 1));
-+		transport_marker_bar = new ArdourCanvas::SimpleRect (*transport_marker_bar_group, 0.0, 0.0,  phys_width, (timebar_height - 1));
- 		transport_marker_bar->property_outline_pixels() = 1;
- 	} else {
--		transport_marker_bar = new ArdourCanvas::SimpleRect (*transport_marker_bar_group, 0.0, 0.0,  physical_screen_width, (timebar_height));
-+		transport_marker_bar = new ArdourCanvas::SimpleRect (*transport_marker_bar_group, 0.0, 0.0,  phys_width, (timebar_height));
- 		transport_marker_bar->property_outline_pixels() = 0;
- 	}
- 	transport_marker_bar->property_outline_what() = (0x1 | 0x8);
- 
- 	marker_bar_group = new ArdourCanvas::Group (*track_canvas->root ());
- 	if (Profile->get_sae()) {
--		marker_bar = new ArdourCanvas::SimpleRect (*marker_bar_group, 0.0, 0.0, physical_screen_width, (timebar_height - 1));
-+		marker_bar = new ArdourCanvas::SimpleRect (*marker_bar_group, 0.0, 0.0, phys_width, (timebar_height - 1));
- 		marker_bar->property_outline_pixels() = 1;
- 	} else {
--		marker_bar = new ArdourCanvas::SimpleRect (*marker_bar_group, 0.0, 0.0, physical_screen_width, (timebar_height));
-+		marker_bar = new ArdourCanvas::SimpleRect (*marker_bar_group, 0.0, 0.0, phys_width, (timebar_height));
- 		marker_bar->property_outline_pixels() = 0;
- 	}
- 	marker_bar->property_outline_what() = (0x1 | 0x8);
- 	
- 	cd_marker_bar_group = new ArdourCanvas::Group (*track_canvas->root ());
- 	if (Profile->get_sae()) {
--		cd_marker_bar = new ArdourCanvas::SimpleRect (*cd_marker_bar_group, 0.0, 0.0, physical_screen_width, (timebar_height - 1));
-+		cd_marker_bar = new ArdourCanvas::SimpleRect (*cd_marker_bar_group, 0.0, 0.0, phys_width, (timebar_height - 1));
- 		cd_marker_bar->property_outline_pixels() = 1;
- 	} else {
--		cd_marker_bar = new ArdourCanvas::SimpleRect (*cd_marker_bar_group, 0.0, 0.0, physical_screen_width, (timebar_height));
-+		cd_marker_bar = new ArdourCanvas::SimpleRect (*cd_marker_bar_group, 0.0, 0.0, phys_width, (timebar_height));
- 		cd_marker_bar->property_outline_pixels() = 0;
- 	}
-  	cd_marker_bar->property_outline_what() = (0x1 | 0x8);
-@@ -235,7 +230,7 @@ Editor::initialize_canvas ()
- 	cd_marker_group = new ArdourCanvas::Group (*timebar_group, 0.0, 0.0);
- 
- 	marker_drag_line_points.push_back(Gnome::Art::Point(0.0, 0.0));
--	marker_drag_line_points.push_back(Gnome::Art::Point(0.0, physical_screen_height));
-+	marker_drag_line_points.push_back(Gnome::Art::Point(0.0, phys_height));
- 
- 	marker_drag_line = new ArdourCanvas::Line (*timebar_group);
- 	marker_drag_line->property_width_pixels() = 1;
-@@ -258,14 +253,14 @@ Editor::initialize_canvas ()
- 	transport_punchin_line->property_x1() = 0.0;
- 	transport_punchin_line->property_y1() = 0.0;
- 	transport_punchin_line->property_x2() = 0.0;
--	transport_punchin_line->property_y2() = physical_screen_height;
-+	transport_punchin_line->property_y2() = phys_height;
- 	transport_punchin_line->hide ();
- 	
- 	transport_punchout_line  = new ArdourCanvas::SimpleLine (*_master_group);
- 	transport_punchout_line->property_x1() = 0.0;
- 	transport_punchout_line->property_y1() = 0.0;
- 	transport_punchout_line->property_x2() = 0.0;
--	transport_punchout_line->property_y2() = physical_screen_height;
-+	transport_punchout_line->property_y2() = phys_height;
- 	transport_punchout_line->hide();
- 	
- 	// used to show zoom mode active zooming
-@@ -382,24 +377,20 @@ Editor::track_canvas_size_allocated ()
- void
- Editor::controls_layout_size_request (Requisition* req)
- {
--	TreeModel::Children rows = route_display_model->children();
--	TreeModel::Children::iterator i;
- 	double pos;
- 	bool changed = false;
- 
--	for (pos = 0, i = rows.begin(); i != rows.end(); ++i) {
--		TimeAxisView *tv = (*i)[route_display_columns.tv];
--		if (tv != 0) {
--			pos += tv->effective_height;
--		}
-+	pos = 0;
-+	for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
-+		pos += (*i)->effective_height;
- 	}
- 
--	gint height = min ((gint) pos, (gint) (physical_screen_height - 600));
-+	gint height = min ((gint) pos, (gint) (physical_screen_height (get_window()) - 600));
- 	gint width = max (edit_controls_vbox.get_width(),  controls_layout.get_width());
- 
- 	/* don't get too big. the fudge factors here are just guesses */
- 
--	width =  min (width, (gint) (physical_screen_width - 300));
-+	width =  min (width, (gint) (physical_screen_width (get_window()) - 300));
- 
- 	if ((req->width != width) || (req->height != height)) {
- 		changed = true;
-diff --git a/gtk2_ardour/editor_mouse.cc b/gtk2_ardour/editor_mouse.cc
-index 15f8b23..e1e4faa 100644
---- a/gtk2_ardour/editor_mouse.cc
-+++ b/gtk2_ardour/editor_mouse.cc
-@@ -3996,8 +3996,6 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
- 		drag_info.x_constrained = !drag_info.x_constrained;
- 	}
- 
--        cerr << "drag done, copy ? " << drag_info.copy << " x-const ? " << drag_info.x_constrained << endl;
--
- 	if (drag_info.copy) {
- 		if (drag_info.x_constrained) {
- 			op_string = _("fixed time region copy");
-@@ -4037,8 +4035,6 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
- 			continue;
- 		}
-                 
--                cerr << "drag delta = " << drag_delta << " rpos was " << rv->region()->position() << endl;
--
- 		if (changed_position && !drag_info.x_constrained && (mouse_mode != MouseRange)) {
- 			where = rv->region()->position() - drag_delta;
- 		} else {
-@@ -4074,8 +4070,6 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
- 				session->add_command (new MementoCommand<Playlist>(*to_playlist, &to_playlist->get_state(), 0));
- 			}
- 
--                        cerr << "Adding region @ " << new_region->position() << " at " << where << endl;
--
- 			to_playlist->add_region (new_region, where);
- 
- 			c.disconnect ();
-@@ -4409,8 +4403,6 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
- 		return;
- 	}
- 
--        cerr << "got " << new_regions.size() << " regions in selection grab\n";
--
- 	/* XXX fix me one day to use all new regions */
- 	
- 	boost::shared_ptr<Region> region (new_regions.front());
-diff --git a/gtk2_ardour/editor_ops.cc b/gtk2_ardour/editor_ops.cc
-index d614a38..a1b47ec 100644
---- a/gtk2_ardour/editor_ops.cc
-+++ b/gtk2_ardour/editor_ops.cc
-@@ -1797,20 +1797,9 @@ Editor::temporal_zoom_region (bool both_axes)
- 			(*t)->set_height (per_track_height);
- 		}
- 		
--		/* hide irrelevant tracks */
--		
--		no_route_list_redisplay = true;
--
--		for (TrackViewList::iterator i = track_views.begin(); i != track_views.end(); ++i) {
--			if (find (tracks.begin(), tracks.end(), (*i)) == tracks.end()) {
--				hide_track_in_display (**i, true);
--			}
--		}
--
--		no_route_list_redisplay = false;
--		redisplay_route_list ();
-+		controls_layout.property_height () = full_canvas_height - canvas_timebars_vsize;
-+		vertical_adjustment.set_value ((*tracks.begin())->y_position );
- 
--		vertical_adjustment.set_value (0);
- 		no_save_visual = false;
- 	}
- 
-@@ -2302,9 +2291,7 @@ Editor::insert_region_list_selection (float times)
- 	RouteTimeAxisView *tv = 0;
- 	boost::shared_ptr<Playlist> playlist;
- 
--	if (clicked_audio_trackview != 0) {
--		tv = clicked_audio_trackview;
--	} else if (!selection->tracks.empty()) {
-+	if (!selection->tracks.empty()) {
- 		if ((tv = dynamic_cast<RouteTimeAxisView*>(selection->tracks.front())) == 0) {
- 			return;
- 		}
-@@ -3113,8 +3100,10 @@ Editor::region_fill_selection ()
- 	}
- 
- 	TreeModel::iterator i = region_list_display.get_selection()->get_selected();
--	boost::shared_ptr<Region> region = (*i)[region_list_columns.region];
--
-+	TreeView::Selection::ListHandle_Path rows = selected->get_selected_rows ();
-+	TreeIter iter  = region_list_model->get_iter (*rows.begin());
-+	boost::shared_ptr<Region> region = (*iter)[region_list_columns.region];
-+	
- 	nframes64_t start = selection->time[clicked_selection].start;
- 	nframes64_t end = selection->time[clicked_selection].end;
- 
-@@ -3135,7 +3124,7 @@ Editor::region_fill_selection ()
- 			continue;
- 		}		
- 		
--                XMLNode &before = playlist->get_state();
-+               XMLNode &before = playlist->get_state();
- 		playlist->add_region (RegionFactory::create (region), start, times);
- 		session->add_command (new MementoCommand<Playlist>(*playlist, &before, &playlist->get_state()));
- 	}
-diff --git a/gtk2_ardour/editor_selection.cc b/gtk2_ardour/editor_selection.cc
-index 37f9968..fd8e5d1 100644
---- a/gtk2_ardour/editor_selection.cc
-+++ b/gtk2_ardour/editor_selection.cc
-@@ -611,8 +611,8 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
- 			*/
- 			
- 			
--			first_frame = entered_regionview->region()->position();
--			last_frame = entered_regionview->region()->last_frame();
-+			first_frame = clicked_regionview->region()->position();
-+			last_frame = clicked_regionview->region()->last_frame();
- 			
- 			for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
- 				if ((*i)->region()->position() < first_frame) {
-@@ -639,9 +639,9 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
- 			   the this one and any selected ones.
- 			*/
- 
--			if (!selection->selected (entered_regionview)) {
-+			if (!selection->selected (clicked_regionview)) {
- 
--				AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&entered_regionview->get_time_axis_view());
-+				AudioTimeAxisView* atv = dynamic_cast<AudioTimeAxisView*> (&clicked_regionview->get_time_axis_view());
- 
- 				if (atv) {
- 
-diff --git a/gtk2_ardour/editor_tempodisplay.cc b/gtk2_ardour/editor_tempodisplay.cc
-index 92efed3..d30981b 100644
---- a/gtk2_ardour/editor_tempodisplay.cc
-+++ b/gtk2_ardour/editor_tempodisplay.cc
-@@ -45,6 +45,7 @@
- #include "ardour_ui.h"
- #include "time_axis_view.h"
- #include "tempo_lines.h"
-+#include "utils.h"
- 
- #include "i18n.h"
- 
-@@ -196,7 +197,7 @@ Editor::draw_measures ()
- 	}
- 
- 	if (tempo_lines == 0) {
--		tempo_lines = new TempoLines(*track_canvas, time_line_group, physical_screen_height);
-+		tempo_lines = new TempoLines(*track_canvas, time_line_group, physical_screen_height (get_window()));
- 	}
- 
- 	tempo_lines->draw(*current_bbt_points, frames_per_unit);
-diff --git a/gtk2_ardour/editor_timefx.cc b/gtk2_ardour/editor_timefx.cc
-index 543c182..2b1ad3c 100644
---- a/gtk2_ardour/editor_timefx.cc
-+++ b/gtk2_ardour/editor_timefx.cc
-@@ -20,6 +20,7 @@
- #include <iostream>
- #include <cstdlib>
- #include <cmath>
-+#include <ctime>
- 
- #include <string>
- 
-@@ -442,6 +443,14 @@ Editor::timefx_thread (void *arg)
- 
- 	tsd->editor.do_timefx (*tsd);
- 
-+        /* GACK! HACK! sleep for a bit so that our request buffer for the GUI
-+           event loop doesn't die before any changes we made are processed
-+           by the GUI ...
-+        */
-+
-+        struct timespec t = { 2, 0 };
-+        nanosleep (&t, 0);
-+
- 	return 0;
- }
- 
-diff --git a/gtk2_ardour/engine_dialog.cc b/gtk2_ardour/engine_dialog.cc
-index edec6c1..c1719ef 100644
---- a/gtk2_ardour/engine_dialog.cc
-+++ b/gtk2_ardour/engine_dialog.cc
-@@ -3,9 +3,11 @@
- #include <fstream>
- #include <map>
- 
-+#include <boost/scoped_ptr.hpp>
- #include <glibmm.h>
- #include <gtkmm/messagedialog.h>
- #include <pbd/xml++.h>
-+#include <pbd/epa.h>
- 
- #ifdef __APPLE__
- #include <CoreAudio/CoreAudio.h>
-@@ -400,6 +402,8 @@ EngineControl::build_command_line (vector<string>& cmd)
- 		cmd.push_back ("-R");
- 		cmd.push_back ("-P");
- 		cmd.push_back (to_string ((uint32_t) floor (priority_spinner.get_value()), std::dec));
-+	} else {
-+		cmd.push_back ("-r"); /* override jackd's default --realtime */
- 	}
- 
- 	if (unlock_memory_button.get_active()) {
-@@ -558,6 +562,17 @@ EngineControl::build_command_line (vector<string>& cmd)
- bool
- EngineControl::engine_running ()
- {
-+        EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
-+        boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
-+
-+        /* revert all environment settings back to whatever they were when ardour started
-+         */
-+
-+        if (global_epa) {
-+                current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
-+                global_epa->restore ();
-+        }
-+	
- 	jack_status_t status;
- 	jack_client_t* c = jack_client_open ("ardourprobe", JackNoStartServer, &status);
- 
-diff --git a/gtk2_ardour/ergonomic-us.bindings.in b/gtk2_ardour/ergonomic-us.bindings.in
-index 523878b..0268140 100644
---- a/gtk2_ardour/ergonomic-us.bindings.in
-+++ b/gtk2_ardour/ergonomic-us.bindings.in
-@@ -284,7 +284,8 @@
- ; (gtk_accel_path "<Actions>/options/FileHeaderFormatCAF" "")
- (gtk_accel_path "<Actions>/Common/ToggleLocations" "<%WINDOW%>l")
- ; (gtk_accel_path "<Actions>/Editor/ToggleGeneric MIDISurface" "")
--(gtk_accel_path "<Actions>/Editor/editor-delete" "BackSpace")
-+(gtk_accel_path "<Actions>/Editor/editor-delete" "Delete")
-+(gtk_accel_path "<Actions>/Editor/editor-alternate-delete" "BackSpace")
- ; (gtk_accel_path "<Actions>/JACK/JACKLatency256" "")
- (gtk_accel_path "<Actions>/Editor/select-all-between-cursors" "F16")
- ; (gtk_accel_path "<Actions>/Editor/LayerAddHigher" "")
-diff --git a/gtk2_ardour/export_range_markers_dialog.cc b/gtk2_ardour/export_range_markers_dialog.cc
-index 5a04b25..6163cab 100644
---- a/gtk2_ardour/export_range_markers_dialog.cc
-+++ b/gtk2_ardour/export_range_markers_dialog.cc
-@@ -111,7 +111,6 @@ string
- ExportRangeMarkersDialog::get_target_filepath(string path, string filename, string postfix)
- {
- 	string target_filepath = Glib::build_filename (path, filename + postfix);
--	struct stat statbuf;
- 	
- 	for (int counter=1; Glib::file_test (target_filepath, Glib::FILE_TEST_EXISTS); counter++) {
- 		// while file exists	
-diff --git a/gtk2_ardour/generic_pluginui.cc b/gtk2_ardour/generic_pluginui.cc
-index 52813aa..bdaedd5 100644
---- a/gtk2_ardour/generic_pluginui.cc
-+++ b/gtk2_ardour/generic_pluginui.cc
-@@ -589,7 +589,7 @@ GenericPluginUI::build_control_ui (guint32 port_index, PBD::Controllable* mcontr
- void
- GenericPluginUI::start_touch (GenericPluginUI::ControlUI* cui)
- {
--	insert->automation_list (cui->port_index).start_touch (insert->session().transport_frame());
-+	insert->automation_list ( cui->port_index).start_touch (insert->session().transport_frame() );
- }
- 
- void
-@@ -603,8 +603,13 @@ GenericPluginUI::stop_touch (GenericPluginUI::ControlUI* cui)
-                 when = insert->session().transport_frame();
-         }
- 
-+		double value = cui->adjustment->get_value();
-+		if (cui->logarithmic) {
-+			value = exp(value);
-+		}
-+
-         if (insert->automation_list (cui->port_index).automation_state() == Auto_Touch) {
--                insert->automation_list (cui->port_index).stop_touch (mark, when);
-+                insert->automation_list (cui->port_index).stop_touch (mark, when, value);
-         }
- }
- 
-diff --git a/gtk2_ardour/lv2_plugin_ui.cc b/gtk2_ardour/lv2_plugin_ui.cc
-index c4f010a..90ee8aa 100644
---- a/gtk2_ardour/lv2_plugin_ui.cc
-+++ b/gtk2_ardour/lv2_plugin_ui.cc
-@@ -18,11 +18,16 @@
- 
- */
- 
-+#include <pbd/pthread_utils.h>
-+
- #include <ardour/insert.h>
- #include <ardour/lv2_plugin.h>
- 
-+#include <gtkmm2ext/gtk_ui.h>
-+
- #include "ardour_ui.h"
- #include "lv2_plugin_ui.h"
-+#include "gui_thread.h"
- 
- using namespace Gtk;
- using namespace ARDOUR;
-@@ -35,10 +40,14 @@ LV2PluginUI::lv2_ui_write(LV2UI_Controller controller,
-              uint32_t         format,
-              const void*      buffer)
- {
--	//cout << "lv2_ui_write" << endl;
- 	LV2PluginUI* me = (LV2PluginUI*)controller;
-+
-+        if (!Gtkmm2ext::UI::instance()->caller_is_ui_thread()) {
-+                PBD::notify_gui_about_thread_creation (pthread_self(), me->_lv2->name());
-+        }
-+
- 	if (*(float*)buffer != me->_values[port_index]) {
--		//cout << "set_parameter " << port_index << ":"  << *(float*)buffer << endl;
-+		// cout << "set_parameter " << port_index << ":"  << *(float*)buffer << endl;
- 		me->_lv2->set_parameter(port_index, *(float*)buffer);
-   }
- }
-@@ -66,6 +75,8 @@ LV2PluginUI::parameter_update (uint32_t port_index, float val)
- 		return;
- 	}
- 
-+        ENSURE_GUI_THREAD(bind (mem_fun (*this, &LV2PluginUI::parameter_update), port_index, val));
-+
- 	const LV2UI_Descriptor* ui_desc = slv2_ui_instance_get_descriptor(_inst);
- 	LV2UI_Handle ui_handle = slv2_ui_instance_get_handle(_inst);
- 	if (ui_desc->port_event) {
-@@ -120,6 +131,7 @@ LV2PluginUI::output_update()
- LV2PluginUI::LV2PluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<LV2Plugin> lv2p)
- 	: PlugUIBase (pi)
- 	, _lv2(lv2p)
-+        , _current_ui_thread (0)
- 	, _inst(NULL)
- 	, _values(NULL)
- 	, _external_ui_ptr(NULL)
-diff --git a/gtk2_ardour/lv2_plugin_ui.h b/gtk2_ardour/lv2_plugin_ui.h
-index 9bb1fe6..0ad2806 100644
---- a/gtk2_ardour/lv2_plugin_ui.h
-+++ b/gtk2_ardour/lv2_plugin_ui.h
-@@ -58,11 +58,11 @@ class LV2PluginUI : public PlugUIBase, public Gtk::VBox
- 	boost::shared_ptr<ARDOUR::LV2Plugin> _lv2;
- 	std::vector<int> _output_ports;
- 	sigc::connection _screen_update_connection;
--	
--	Gtk::Widget*   _gui_widget;
--	SLV2UIInstance _inst;
--	float*         _values;
--
-+        pthread_t        _current_ui_thread;
-+	Gtk::Widget*     _gui_widget;
-+	SLV2UIInstance   _inst;
-+	float*           _values;
-+        
- 	struct lv2_external_ui_host _external_ui_host;
- 	LV2_Feature _external_ui_feature;
- 	struct lv2_external_ui* _external_ui_ptr;
-diff --git a/gtk2_ardour/main.cc b/gtk2_ardour/main.cc
-index 7a34e93..7d9ce7f 100644
---- a/gtk2_ardour/main.cc
-+++ b/gtk2_ardour/main.cc
-@@ -19,6 +19,8 @@
- 
- #include <cstdlib>
- #include <signal.h>
-+#include <cerrno>
-+#include <fstream>
- 
- #include <sigc++/bind.h>
- #include <gtkmm/settings.h>
-@@ -28,6 +30,7 @@
- #include <pbd/textreceiver.h>
- #include <pbd/failed_constructor.h>
- #include <pbd/pthread_utils.h>
-+#include <pbd/epa.h>
- 
- #include <jack/jack.h>
- 
-@@ -66,17 +69,18 @@ static const char* localedir = LOCALEDIR;
- 
- #include <mach-o/dyld.h>
- #include <sys/param.h>
--#include <fstream>
- 
- extern void set_language_preference (); // cocoacarbon.mm
- 
- void
--fixup_bundle_environment ()
-+fixup_bundle_environment (int argc, char* argv[])
- {
- 	if (!getenv ("ARDOUR_BUNDLED")) {
- 		return;
- 	}
- 	
-+        EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true));
-+
- 	set_language_preference ();
- 
- 	char execpath[MAXPATHLEN+1];
-@@ -95,6 +99,15 @@ fixup_bundle_environment ()
- 	*/
- 
- 	path = dir_path;
-+
-+	/* JACK is often in /usr/local/bin and since Info.plist refuses to 
-+	   set PATH, we have to force this in order to discover a running
-+	   instance of JACK ...
-+	*/
-+	
-+	path += ':';
-+	path += "/usr/local/bin";
-+
- 	if (cstr) {
- 		path += ':';
- 		path += cstr;
-@@ -102,15 +115,17 @@ fixup_bundle_environment ()
- 	setenv ("PATH", path.c_str(), 1);
- 
- 	path = dir_path;
--	path += "/../Resources";
-+	path += "/../Resources:";
- 	path += dir_path;
--	path += "/../Resources/Surfaces";
-+	path += "/../Resources/Surfaces:";
- 	path += dir_path;
--	path += "/../Resources/Panners";
-+	path += "/../Resources/Panners:";
- 
- 	setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
- 
--	path = dir_path;
-+        path = get_user_ardour_path ();
-+        path += ':';
-+	path += dir_path;
- 	path += "/../Resources/icons:";
- 	path += dir_path;
- 	path += "/../Resources/pixmaps:";
-@@ -163,23 +178,16 @@ fixup_bundle_environment ()
- 	
- 	setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
- 
--	cstr = getenv ("LV2_PATH");
--	if (cstr) {
--		path = cstr;
--		path += ':';
--	} else {
--		path = "";
--	}
--	path += dir_path;
--	path += "/../Plugins";
--	
--	setenv ("LV2_PATH", path.c_str(), 1);
--
- 	path = dir_path;
- 	path += "/../Frameworks/clearlooks";
- 
- 	setenv ("GTK_PATH", path.c_str(), 1);
- 
-+        /* unset GTK_RC_FILES so that we only load the RC files that we define
-+         */
-+
-+        unsetenv ("GTK_RC_FILES");
-+
- 	if (!ARDOUR::translations_are_disabled ()) {
- 
- 		path = dir_path;
-@@ -249,6 +257,152 @@ fixup_bundle_environment ()
- 	}
- }
- 
-+#else
-+
-+void
-+fixup_bundle_environment (int argc, char* argv[])
-+{
-+	if (!getenv ("ARDOUR_BUNDLED")) {
-+		return;
-+	}
-+
-+        EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
-+	
-+	Glib::ustring exec_path = argv[0];
-+	Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (exec_path));
-+	Glib::ustring path;
-+	const char *cstr = getenv ("PATH");
-+
-+	/* ensure that we find any bundled executables (e.g. JACK),
-+	   and find them before any instances of the same name
-+	   elsewhere in PATH
-+	*/
-+
-+        /* note that this function is POSIX/Linux specific, so using / as 
-+           a dir separator in this context is just fine.
-+        */
-+
-+	path = dir_path;
-+	path += "/etc:";
-+	path += dir_path;
-+	path += "/lib/surfaces:";
-+	path += dir_path;
-+	path += "/lib/panners:";
-+
-+	setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
-+
-+        path = get_user_ardour_path ();
-+        path += ':';
-+	path += dir_path;
-+	path += "/etc/icons:";
-+	path += dir_path;
-+	path += "/etc/pixmaps:";
-+	path += dir_path;
-+	path += "/share:";
-+	path += dir_path;
-+	path += "/etc";
-+
-+	setenv ("ARDOUR_PATH", path.c_str(), 1);
-+	setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
-+	setenv ("ARDOUR_DATA_PATH", path.c_str(), 1);
-+
-+	path = dir_path;
-+	path += "/etc";
-+	setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
-+
-+	cstr = getenv ("LADSPA_PATH");
-+	if (cstr) {
-+		path = cstr;
-+		path += ':';
-+	} else {
-+		path = "";
-+	}
-+	path += dir_path;
-+	path += "/lib/plugins";
-+	
-+	setenv ("LADSPA_PATH", path.c_str(), 1);
-+
-+	cstr = getenv ("VAMP_PATH");
-+	if (cstr) {
-+		path = cstr;
-+		path += ':';
-+	} else {
-+		path = "";
-+	}
-+	path += dir_path;
-+	path += "/lib";
-+	
-+	setenv ("VAMP_PATH", path.c_str(), 1);
-+
-+	cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
-+	if (cstr) {
-+		path = cstr;
-+		path += ':';
-+	} else {
-+		path = "";
-+	}
-+	path += dir_path;
-+	path += "/lib/surfaces";
-+	
-+	setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
-+
-+	path = dir_path;
-+	path += "/lib/clearlooks";
-+
-+	setenv ("GTK_PATH", path.c_str(), 1);
-+
-+        /* unset GTK_RC_FILES so that we only load the RC files that we define
-+         */
-+
-+        unsetenv ("GTK_RC_FILES");
-+
-+	if (!ARDOUR::translations_are_disabled ()) {
-+                path = dir_path;
-+                path += "/share/locale";
-+                
-+                localedir = strdup (path.c_str());
-+                setenv ("GTK_LOCALEDIR", localedir, 1);
-+        }
-+
-+	/* write a pango.rc file and tell pango to use it. we'd love
-+	   to put this into the Ardour.app bundle and leave it there,
-+	   but the user may not have write permission. so ... 
-+
-+	   we also have to make sure that the user ardour directory
-+	   actually exists ...
-+	*/
-+
-+	if (g_mkdir_with_parents (ARDOUR::get_user_ardour_path().c_str(), 0755) < 0) {
-+		error << string_compose (_("cannot create user ardour folder %1 (%2)"), ARDOUR::get_user_ardour_path(), strerror (errno))
-+		      << endmsg;
-+	} else {
-+
-+                Glib::ustring mpath;
-+
-+		path = Glib::build_filename (ARDOUR::get_user_ardour_path(), "pango.rc");
-+
-+		std::ofstream pangorc (path.c_str());
-+		if (!pangorc) {
-+			error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
-+                } else {
-+                        mpath = Glib::build_filename (ARDOUR::get_user_ardour_path(), "pango.modules");
-+                        
-+			pangorc << "[Pango]\nModuleFiles=";
-+			pangorc << mpath << endl;
-+			pangorc.close ();
-+                }
-+
-+                setenv ("PANGO_RC_FILE", path.c_str(), 1);
-+
-+                /* similar for GDK pixbuf loaders, but there's no RC file required
-+                   to specify where it lives.
-+                */
-+
-+                mpath = Glib::build_filename (ARDOUR::get_user_ardour_path(), "gdk-pixbuf.loaders");
-+                setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
-+	}
-+}
-+
- #endif
- 
- static gboolean
-@@ -312,10 +466,8 @@ int main (int argc, char* argv[])
- #endif
- {
- 	vector<Glib::ustring> null_file_list;
--	
--#ifdef __APPLE__
--	fixup_bundle_environment ();
--#endif
-+
-+	fixup_bundle_environment (argc, argv);
- 
-         Glib::thread_init();
- 
-diff --git a/gtk2_ardour/mnemonic-us.bindings.in b/gtk2_ardour/mnemonic-us.bindings.in
-index f5d776a..22df5ca 100644
---- a/gtk2_ardour/mnemonic-us.bindings.in
-+++ b/gtk2_ardour/mnemonic-us.bindings.in
-@@ -140,6 +140,7 @@
- (gtk_accel_path "<Actions>/Transport/GotoStart" "Home")
- (gtk_accel_path "<Actions>/Transport/GotoEnd" "End")
- (gtk_accel_path "<Actions>/Editor/editor-delete" "Delete")
-+(gtk_accel_path "<Actions>/Editor/editor-alternate-delete" "BackSpace")
- 
- (gtk_accel_path "<Actions>/Editor/playhead-to-edit" "Return")
- (gtk_accel_path "<Actions>/Editor/edit-to-playhead" "<%SECONDARY%>Return")
-@@ -175,7 +176,7 @@
- (gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-start" "F1")
- (gtk_accel_path "<Actions>/Editor/edit-cursor-to-range-end" "F2")
- (gtk_accel_path "<Actions>/Editor/crop" "F3")
--(gtk_accel_path "<Actions>/Editor/separate" "F4")
-+(gtk_accel_path "<Actions>/Editor/editor-separate" "F4")
- (gtk_accel_path "<Actions>/Editor/pitch-<%TERTIARY%>-region" "F5")
- (gtk_accel_path "<Actions>/Editor/select-range-between-cursors" "F6")
- (gtk_accel_path "<Actions>/Common/ToggleMaximalEditor" "F11")
-diff --git a/gtk2_ardour/po/cs.po b/gtk2_ardour/po/cs.po
-index 0408c49b..5cb54ad 100644
---- a/gtk2_ardour/po/cs.po
-+++ b/gtk2_ardour/po/cs.po
-@@ -8,7 +8,7 @@
- #, fuzzy
- msgid ""
- msgstr ""
--"Project-Id-Version: gtk-ardour 0.347.2\n"
-+"Project-Id-Version: gtk2_ardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2008-10-20 19:01+0100\n"
- "PO-Revision-Date: 2010-02-03 13:57-0500\n"
-diff --git a/gtk2_ardour/po/de.po b/gtk2_ardour/po/de.po
-index adccd6f..dcc9126 100644
---- a/gtk2_ardour/po/de.po
-+++ b/gtk2_ardour/po/de.po
-@@ -7,7 +7,7 @@
- # Robert Schwede <robert-schwede at gmx.de>, 2009.
- msgid ""
- msgstr ""
--"Project-Id-Version: gtk-ardour 0.347.2\n"
-+"Project-Id-Version: gtk2_ardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2009-07-05 19:46+0100\n"
- "PO-Revision-Date: 2009-08-12 10:14+0100\n"
-diff --git a/gtk2_ardour/po/el.po b/gtk2_ardour/po/el.po
-index 14a9fef..59af2b0 100644
---- a/gtk2_ardour/po/el.po
-+++ b/gtk2_ardour/po/el.po
-@@ -5,7 +5,7 @@
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: gtk-ardour 0.347.2\n"
-+"Project-Id-Version: gtk2_ardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2005-01-11 13:00+0200\n"
- "PO-Revision-Date: 2007-04-11 02:27+0200\n"
-diff --git a/gtk2_ardour/po/es.po b/gtk2_ardour/po/es.po
-index f4e3727..6a2166a 100644
---- a/gtk2_ardour/po/es.po
-+++ b/gtk2_ardour/po/es.po
-@@ -1,6 +1,6 @@
- msgid ""
- msgstr ""
--"Project-Id-Version: Ardour gtk2 translation\n"
-+"Project-Id-Version: gtk2_ardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2010-01-22 19:05+0100\n"
- "PO-Revision-Date: \n"
-diff --git a/gtk2_ardour/po/fr.po b/gtk2_ardour/po/fr.po
-index ac47b86..cfc8115 100644
---- a/gtk2_ardour/po/fr.po
-+++ b/gtk2_ardour/po/fr.po
-@@ -5,7 +5,7 @@
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: PACKAGE VERSION\n"
-+"Project-Id-Version: gtk2_ardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2010-04-27 16:38+0200\n"
- "PO-Revision-Date: 2010-04-27 16:39+0100\n"
-diff --git a/gtk2_ardour/po/it.po b/gtk2_ardour/po/it.po
-index edc4b62..59d1800 100644
---- a/gtk2_ardour/po/it.po
-+++ b/gtk2_ardour/po/it.po
-@@ -1,6 +1,6 @@
- msgid ""
- msgstr ""
--"Project-Id-Version: 2.8.1\n"
-+"Project-Id-Version: gtk2_ardour\n"
- "POT-Creation-Date: \n"
- "PO-Revision-Date: \n"
- "Last-Translator: Emanuele Costantini <sound at ecciproduzioni.com>\n"
-diff --git a/gtk2_ardour/po/nn.po b/gtk2_ardour/po/nn.po
-index 4e6c590..4d7241f 100755
---- a/gtk2_ardour/po/nn.po
-+++ b/gtk2_ardour/po/nn.po
-@@ -5,12 +5,12 @@
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: PACKAGE VERSION\n"
-+"Project-Id-Version: gtk2_ardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2009-12-24 15:13+0100\n"
- "PO-Revision-Date: 2010-01-17 21:11+0100\n"
- "Last-Translator: Eivind Ødegård <gingermig at yahoo.no>\n"
--"Language-Team: LANGUAGE <LL at li.org>\n"
-+"Language-Team: \n"
- "MIME-Version: 1.0\n"
- "Content-Type: text/plain; charset=UTF-8\n"
- "Content-Transfer-Encoding: 8bit\n"
-diff --git a/gtk2_ardour/po/pt.po b/gtk2_ardour/po/pt.po
-index 1a10e8a..72b8661 100644
---- a/gtk2_ardour/po/pt.po
-+++ b/gtk2_ardour/po/pt.po
-@@ -8,7 +8,7 @@
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: ardour 0.688.4\n"
-+"Project-Id-Version: gtk2_ardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2006-06-27 13:00-0400\n"
- "PO-Revision-Date: 2005-08-15 21:50-0000\n"
-diff --git a/gtk2_ardour/po/pt_PT.po b/gtk2_ardour/po/pt_PT.po
-index c627f84..cadb6d7 100644
---- a/gtk2_ardour/po/pt_PT.po
-+++ b/gtk2_ardour/po/pt_PT.po
-@@ -5,7 +5,7 @@
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: gtk2_ardour rev.1702\n"
-+"Project-Id-Version: gtk2_ardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2007-04-08 13:00+0100\n"
- "PO-Revision-Date: 2007-04-15 19:00+0100\n"
-diff --git a/gtk2_ardour/po/ru.po b/gtk2_ardour/po/ru.po
-index a6f7301..1732c59 100644
---- a/gtk2_ardour/po/ru.po
-+++ b/gtk2_ardour/po/ru.po
-@@ -6,7 +6,7 @@
- # Alexandre Prokoudine <alexandre.prokoudine at gmail.com>, 2006, 2007, 2009
- msgid ""
- msgstr ""
--"Project-Id-Version: ru_RU\n"
-+"Project-Id-Version: gtk2_ardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2010-01-20 01:34+0300\n"
- "PO-Revision-Date: 2010-01-20 04:25+0300\n"
-diff --git a/gtk2_ardour/po/sv.po b/gtk2_ardour/po/sv.po
-index d6afa0e..9cd8361 100644
---- a/gtk2_ardour/po/sv.po
-+++ b/gtk2_ardour/po/sv.po
-@@ -5,7 +5,7 @@
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: ardour-gtk 1.0.2\n"
-+"Project-Id-Version: gtk2_ardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2006-06-12 22:09+0200\n"
- "PO-Revision-Date: 2006-06-26 23:57+GMT+1\n"
-diff --git a/gtk2_ardour/public_editor.h b/gtk2_ardour/public_editor.h
-index 690c0a2..74e6c36 100644
---- a/gtk2_ardour/public_editor.h
-+++ b/gtk2_ardour/public_editor.h
-@@ -152,7 +152,6 @@ class PublicEditor : public Gtk::Window, public PBD::StatefulThingWithGoingAway
- 	virtual void toggle_follow_playhead () = 0;
- 	virtual bool follow_playhead() const = 0;
- 	virtual bool dragging_playhead() const = 0;
--	virtual double get_physical_screen_width() const = 0;
- 	virtual void ensure_float (Gtk::Window&) = 0;
- 	virtual void show_window () = 0;
- 	virtual TrackViewList* get_valid_views (TimeAxisView*, ARDOUR::RouteGroup* grp = 0) = 0;
-diff --git a/gtk2_ardour/rhythm_ferret.cc b/gtk2_ardour/rhythm_ferret.cc
-index 4a4f3d4..abf53ef 100644
---- a/gtk2_ardour/rhythm_ferret.cc
-+++ b/gtk2_ardour/rhythm_ferret.cc
-@@ -72,14 +72,14 @@ RhythmFerret::RhythmFerret (PublicEditor& e)
- 	, trigger_gap_adjustment (3, 0, 100, 1, 10)
- 	, trigger_gap_spinner (trigger_gap_adjustment)
- 	, trigger_gap_label (_("Trigger gap (msecs)"))
--	, action_button (Stock::APPLY)
-+	, action_button ( _("Split On Onsets"))
- 
- {
- 	upper_hpacker.set_spacing (6);
- 
- 	upper_hpacker.pack_start (ferret_frame, true, true);
--	upper_hpacker.pack_start (selection_frame, true, true);
--	upper_hpacker.pack_start (operation_frame, true, true);
-+//	upper_hpacker.pack_start (selection_frame, true, true);
-+//	upper_hpacker.pack_start (operation_frame, true, true);
- 
- 	op_packer.pack_start (region_split_button, false, false);
- 	op_packer.pack_start (tempo_button, false, false);
-@@ -219,12 +219,13 @@ RhythmFerret::get_analysis_mode () const
- RhythmFerret::Action
- RhythmFerret::get_action () const
- {
--	if (tempo_button.get_active()) {
-+/*
-+ * 	if (tempo_button.get_active()) {
- 		return DefineTempoMap;
- 	} else if (region_conform_button.get_active()) {
- 		return ConformRegion;
- 	}
--
-+*/
- 	return SplitRegion;
- }
- 
-diff --git a/gtk2_ardour/sfdb_ui.cc b/gtk2_ardour/sfdb_ui.cc
-index c83f1c5..87a6ae6 100644
---- a/gtk2_ardour/sfdb_ui.cc
-+++ b/gtk2_ardour/sfdb_ui.cc
-@@ -979,6 +979,7 @@ SoundFileOmega::reset_options ()
- 			}
- 			if (same_size) {
- 				channel_strings.push_back (_("all files in one track"));
-+				channel_strings.push_back (_("merge files"));
- 			}
- 			
- 		}
-diff --git a/gtk2_ardour/streamview.cc b/gtk2_ardour/streamview.cc
-index ce532ba..d75bc24 100644
---- a/gtk2_ardour/streamview.cc
-+++ b/gtk2_ardour/streamview.cc
-@@ -61,7 +61,7 @@ StreamView::StreamView (RouteTimeAxisView& tv)
- 	canvas_rect = new ArdourCanvas::SimpleRect (*_background_group);
- 	canvas_rect->property_x1() = 0.0;
- 	canvas_rect->property_y1() = 0.0;
--	canvas_rect->property_x2() = _trackview.editor.get_physical_screen_width();
-+	canvas_rect->property_x2() = physical_screen_width (_trackview.editor.get_window());
- 	canvas_rect->property_y2() = (double) tv.current_height();
- 
- 	canvas_rect->property_outline_what() = (guint32) (0x1|0x2|0x8);  // outline ends and bottom 
-diff --git a/gtk2_ardour/utils.cc b/gtk2_ardour/utils.cc
-index 854b5f7..3c58a27 100644
---- a/gtk2_ardour/utils.cc
-+++ b/gtk2_ardour/utils.cc
-@@ -861,6 +861,7 @@ convert_color_channel (guint8 src,
- 	return alpha ? ((guint (src) << 8) - src) / alpha : 0;
- }
- 
-+
- void
- convert_bgra_to_rgba (guint8 const* src,
- 		      guint8*       dst,
-@@ -870,20 +871,42 @@ convert_bgra_to_rgba (guint8 const* src,
- 	guint8 const* src_pixel = src;
- 	guint8*       dst_pixel = dst;
- 	
--	for (int y = 0; y < height; y++)
--		for (int x = 0; x < width; x++)
--		{
--			dst_pixel[0] = convert_color_channel (src_pixel[2],
--							      src_pixel[3]);
--			dst_pixel[1] = convert_color_channel (src_pixel[1],
--							      src_pixel[3]);
--			dst_pixel[2] = convert_color_channel (src_pixel[0],
--							      src_pixel[3]);
--			dst_pixel[3] = src_pixel[3];
--			
--			dst_pixel += 4;
--			src_pixel += 4;
--		}
-+	for (int y = 0; y < height; y++) {
-+	  for (int x = 0; x < width; x++) {
-+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-+	    /* Cairo [ B G R A ] is actually  [ B G R A ] in memory SOURCE
-+	                                        0 1 2 3
-+	       Pixbuf [ R G B A ] is actually [ R G B A ] in memory DEST
-+	    */
-+	    dst_pixel[0] = convert_color_channel (src_pixel[2],
-+						  src_pixel[3]); // R [0] <= [ 2 ]
-+	    dst_pixel[1] = convert_color_channel (src_pixel[1],
-+						  src_pixel[3]); // G [1] <= [ 1 ]
-+	    dst_pixel[2] = convert_color_channel (src_pixel[0],  
-+						  src_pixel[3]); // B [2] <= [ 0 ]
-+	    dst_pixel[3] = src_pixel[3]; // alpha
-+	    
-+#elif G_BYTE_ORDER == G_BIG_ENDIAN
-+	    /* Cairo [ B G R A ] is actually  [ A R G B ] in memory SOURCE
-+	                                        0 1 2 3
-+	       Pixbuf [ R G B A ] is actually [ R G B A ] in memory DEST
-+	    */
-+	    dst_pixel[0] = convert_color_channel (src_pixel[1],
-+						  src_pixel[0]); // R [0] <= [ 1 ]
-+	    dst_pixel[1] = convert_color_channel (src_pixel[2],
-+						  src_pixel[0]); // G [1] <= [ 2 ]
-+	    dst_pixel[2] = convert_color_channel (src_pixel[3],
-+						  src_pixel[0]); // B [2] <= [ 3 ]
-+	    dst_pixel[3] = src_pixel[0]; // alpha
-+	    
-+#else
-+#error ardour does not currently support PDP-endianess
-+#endif			
-+
-+	    dst_pixel += 4;
-+	    src_pixel += 4;
-+	  }
-+	}
- }
- 
- Glib::RefPtr<Gdk::Pixbuf>
-@@ -917,3 +940,33 @@ pixbuf_from_ustring(const ustring& name, Pango::FontDescription* font, uint32_t
- 
- 	return buf;
- }
-+
-+int
-+physical_screen_height (Glib::RefPtr<Gdk::Window> win)
-+{
-+        GdkScreen* scr = gdk_screen_get_default();
-+
-+        if (win) {
-+                GdkRectangle r;
-+                gint monitor = gdk_screen_get_monitor_at_window (scr, win->gobj());
-+                gdk_screen_get_monitor_geometry (scr, monitor, &r);
-+                return r.height;
-+        } else {
-+                return gdk_screen_get_height (scr);
-+        }
-+}
-+
-+int
-+physical_screen_width (Glib::RefPtr<Gdk::Window> win)
-+{
-+        GdkScreen* scr = gdk_screen_get_default();
-+        
-+        if (win) {
-+                GdkRectangle r;
-+                gint monitor = gdk_screen_get_monitor_at_window (scr, win->gobj());
-+                gdk_screen_get_monitor_geometry (scr, monitor, &r);
-+                return r.width;
-+        } else {
-+                return gdk_screen_get_width (scr);
-+        }
-+}
-diff --git a/gtk2_ardour/utils.h b/gtk2_ardour/utils.h
-index ac62f01..61d5f4f 100644
---- a/gtk2_ardour/utils.h
-+++ b/gtk2_ardour/utils.h
-@@ -100,4 +100,7 @@ Glib::RefPtr<Gdk::Pixbuf> pixbuf_from_ustring (const Glib::ustring& name,
- 					       int clip_width,
- 					       int clip_height);
- 
-+int physical_screen_height (Glib::RefPtr<Gdk::Window>);
-+int physical_screen_width (Glib::RefPtr<Gdk::Window>);
-+
- #endif /* __ardour_gtk_utils_h__ */
-diff --git a/libs/appleutility/CAAudioFile.h b/libs/appleutility/CAAudioFile.h
-index ce22bfe..594545a 100644
---- a/libs/appleutility/CAAudioFile.h
-+++ b/libs/appleutility/CAAudioFile.h
-@@ -114,7 +114,6 @@ public:
- 				// or the file's sample rate is 0 (unknown)
- 
- #if CAAF_USE_EXTAUDIOFILE
--#warning HERE WE ARE
- public:
- 	CAAudioFile() : mExtAF(NULL) { std::cerr << "Constructing CAAudioFile\n"; }
- 	virtual ~CAAudioFile() { std::cerr << "Destroying CAAudiofile @ " << this << std::endl; if (mExtAF) Close(); }
-diff --git a/libs/appleutility/CAAudioUnit.cpp b/libs/appleutility/CAAudioUnit.cpp
-index aaf57f2..db1056d 100644
---- a/libs/appleutility/CAAudioUnit.cpp
-+++ b/libs/appleutility/CAAudioUnit.cpp
-@@ -229,7 +229,7 @@ CAAudioUnit::CAAudioUnit (const CAComponent& inComp)
- }
- 
- CAAudioUnit::CAAudioUnit (const AUNode &inNode, const AudioUnit& inUnit)
--	: mComp (inUnit), mDataPtr(new AUState (inNode, inUnit)) 
-+	: mComp (inUnit), mDataPtr(new AUState (inNode, inUnit))
- {
- }
- 
-diff --git a/libs/appleutility/CAAudioUnit.h b/libs/appleutility/CAAudioUnit.h
-index 810b81b..b3493a5 100644
---- a/libs/appleutility/CAAudioUnit.h
-+++ b/libs/appleutility/CAAudioUnit.h
-@@ -57,6 +57,7 @@
- #endif
- 
- #include <vector>
-+#include <set>
- #include "CAStreamBasicDescription.h"
- #include "CAComponent.h"
- #include "CAAudioChannelLayout.h"
-@@ -328,14 +329,14 @@ public:
- #pragma mark __Print	
- 	void					Print () const { Print (stdout); }
- 	void					Print (FILE* file) const;
--	
-+
- private:
- 	CAComponent				mComp;
- 	
- 	class AUState;
- 	AUState*		mDataPtr;
--		
--		// this can throw - so wrap this up in a static that returns a result code...
-+	
-+	// this can throw - so wrap this up in a static that returns a result code...
- 	CAAudioUnit (const CAComponent& inComp);
- 
- 	bool				HasDynamicScope (AudioUnitScope inScope, SInt32 &outTotalNumChannels) const;
-diff --git a/libs/ardour/SConscript b/libs/ardour/SConscript
-index 346ff3c..5a83039 100644
---- a/libs/ardour/SConscript
-+++ b/libs/ardour/SConscript
-@@ -320,6 +320,7 @@ else:
- 	
- if ardour['LV2']:
- 	ardour.Merge ([ libraries['slv2'] ])
-+	ardour.Merge ([ libraries['rasqal'] ])
- 
- if ardour['LIBLO']:
- 	ardour.Merge ([ libraries['lo'] ])
-diff --git a/libs/ardour/ardour/audio_unit.h b/libs/ardour/ardour/audio_unit.h
-index 548936c..cc1604f 100644
---- a/libs/ardour/ardour/audio_unit.h
-+++ b/libs/ardour/ardour/audio_unit.h
-@@ -34,6 +34,7 @@
- 
- #include <AudioUnit/AudioUnit.h>
- #include <AudioUnit/AudioUnitProperties.h>
-+#include <AudioToolbox/AudioUnitUtilities.h>
- #include <appleutility/AUParamInfo.h>
- 
- #include <boost/shared_ptr.hpp>
-@@ -141,6 +142,16 @@ class AUPlugin : public ARDOUR::Plugin
- 
- 	static std::string maybe_fix_broken_au_id (const std::string&);
- 
-+	/* this MUST be called from thread in which you want to receive notifications
-+	   about parameter changes.
-+	*/
-+	int create_parameter_listener (AUEventListenerProc callback, void *arg, float interval_secs);
-+	/* these can be called from any thread but SHOULD be called from the same thread
-+	   that will receive parameter change notifications.
-+	*/
-+	int listen_to_parameter (uint32_t param_id);
-+	int end_listen_to_parameter (uint32_t param_id);
-+
-   private:
-         boost::shared_ptr<CAComponent> comp;
-         boost::shared_ptr<CAAudioUnit> unit;
-@@ -176,20 +187,26 @@ class AUPlugin : public ARDOUR::Plugin
- 	int set_stream_format (int scope, uint32_t cnt, AudioStreamBasicDescription&);
- 	void discover_parameters ();
- 
--	std::vector<std::pair<uint32_t, uint32_t> > parameter_map;
- 	uint32_t current_maxbuf;
-         nframes_t current_offset;
-         nframes_t cb_offset;
-         vector<Sample*>* current_buffers;
-         nframes_t frames_processed;
- 	
-+	typedef std::map<uint32_t, uint32_t> ParameterMap;
-+	ParameterMap parameter_map;
- 	std::vector<AUParameterDescriptor> descriptors;
-+	AUEventListenerRef _parameter_listener;
-+	void * _parameter_listener_arg;
- 	void init ();
- 
- 	void discover_factory_presets ();
- 
- 	bool      last_transport_rolling;
- 	float     last_transport_speed;
-+
-+	static void _parameter_change_listener (void* /*arg*/, void* /*src*/, const AudioUnitEvent* event, UInt64 host_time, Float32 new_value);
-+	void parameter_change_listener (void* /*arg*/, void* /*src*/, const AudioUnitEvent* event, UInt64 host_time, Float32 new_value);
- };
- 	
- typedef boost::shared_ptr<AUPlugin> AUPluginPtr;
-diff --git a/libs/ardour/ardour/audiofilesource.h b/libs/ardour/ardour/audiofilesource.h
-index a3cebd1..b91ce79 100644
---- a/libs/ardour/ardour/audiofilesource.h
-+++ b/libs/ardour/ardour/audiofilesource.h
-@@ -178,6 +178,7 @@ class AudioFileSource : public AudioSource {
- 	Glib::ustring broken_peak_path (Glib::ustring audio_path);
- 
- 	void fix_writable_flags ();
-+	void prevent_deletion ();
- };
- 
- } // namespace ARDOUR
-diff --git a/libs/ardour/ardour/automation_event.h b/libs/ardour/ardour/automation_event.h
-index 1a3918b..45227dc 100644
---- a/libs/ardour/ardour/automation_event.h
-+++ b/libs/ardour/ardour/automation_event.h
-@@ -83,6 +83,7 @@ class AutomationList : public PBD::StatefulDestructible
- 
- 	void freeze();
- 	void thaw ();
-+        int8_t frozen() const { return _frozen; }
- 
- 	AutomationEventList::size_type size() const { return events.size(); }
- 	bool empty() const { return events.empty(); }
-@@ -133,7 +134,7 @@ class AutomationList : public PBD::StatefulDestructible
- 	}
- 
- 	void start_touch (double when);
--	void stop_touch (bool mark, double when);
-+	void stop_touch (bool mark, double when, double value);
-         bool touching() const { return g_atomic_int_get (&_touching); }
- 
- 	void set_yrange (double min, double max) {
-diff --git a/libs/ardour/ardour/configuration_variable.h b/libs/ardour/ardour/configuration_variable.h
-index c9b9890..32d605e 100644
---- a/libs/ardour/ardour/configuration_variable.h
-+++ b/libs/ardour/ardour/configuration_variable.h
-@@ -24,6 +24,7 @@
- #include <ostream>
- 
- #include <pbd/xml++.h>
-+#include <pbd/enumwriter.h>
- 
- #include "ardour/utils.h"
- 
-@@ -113,9 +114,9 @@ class ConfigVariable : public ConfigVariableBase
- 					if ((prop = child->property ("name")) != 0) {
- 						if (prop->value() == _name) {
- 							if ((prop = child->property ("value")) != 0) {
--								std::stringstream ss;
--								ss << prop->value();
--								ss >> value;
-+                                                                std::stringstream ss;
-+                                                                ss << enum_validate (value, prop->value());
-+                                                                ss >> value;
- 								_owner = (ConfigVariableBase::Owner)(_owner |owner);
- 								return true;
- 							}
-@@ -138,12 +139,12 @@ class ConfigVariable : public ConfigVariableBase
- 			for (oiter = olist.begin(); oiter != olist.end(); ++oiter) {
- 				
- 				option = *oiter;
--				
-+                                
- 				if (option->name() == _name) {
- 					if ((opt_prop = option->property ("val")) != 0) {
--						std::stringstream ss;
--						ss << opt_prop->value();
--						ss >> value;
-+                                                std::stringstream ss;
-+                                                ss << enum_validate (value, opt_prop->value());
-+                                                ss >> value;
- 						_owner = (ConfigVariableBase::Owner)(_owner |owner);
- 						return true;
- 					}
-diff --git a/libs/ardour/ardour/configuration_vars.h b/libs/ardour/ardour/configuration_vars.h
-index 31a2ae9..8b95ecf 100644
---- a/libs/ardour/ardour/configuration_vars.h
-+++ b/libs/ardour/ardour/configuration_vars.h
-@@ -159,6 +159,7 @@ CONFIG_VARIABLE (bool, use_overlap_equivalency, "use-overlap-equivalency", false
- CONFIG_VARIABLE (bool, periodic_safety_backups, "periodic-safety-backups", true)
- CONFIG_VARIABLE (uint32_t, periodic_safety_backup_interval, "periodic-safety-backup-interval", 120)
- CONFIG_VARIABLE (float, automation_interval, "automation-interval", 50)
-+CONFIG_VARIABLE (float, automation_thinning_strength, "automation-thinning-strength", 10)
- CONFIG_VARIABLE (bool, sync_all_route_ordering, "sync-all-route-ordering", true)
- CONFIG_VARIABLE (bool, only_copy_imported_files, "only-copy-imported-files", false)
- CONFIG_VARIABLE (bool, new_plugins_active, "new-plugins-active", true)
-diff --git a/libs/ardour/ardour/port.h b/libs/ardour/ardour/port.h
-index 9cf14d9..ef4d92b 100644
---- a/libs/ardour/ardour/port.h
-+++ b/libs/ardour/ardour/port.h
-@@ -145,13 +145,8 @@ class Port : public sigc::trackable {
- 		jack_port_request_monitor (_port, yn);
- 	}
- 
--	nframes_t latency () const {
--		return jack_port_get_latency (_port);
--	}
--
--	void set_latency (nframes_t nframes) {
--		jack_port_set_latency (_port, nframes);
--	}
-+	nframes_t latency () const;
-+	void set_latency (nframes_t nframes);
- 
- 	sigc::signal<void,bool> MonitorInputChanged;
- 	sigc::signal<void,bool> ClockSyncChanged;
-diff --git a/libs/ardour/ardour/session.h b/libs/ardour/ardour/session.h
-index 2bd8d74..cd7e52c 100644
---- a/libs/ardour/ardour/session.h
-+++ b/libs/ardour/ardour/session.h
-@@ -444,6 +444,7 @@ class Session : public PBD::StatefulDestructible
- 	nframes_t worst_output_latency () const { return _worst_output_latency; }
- 	nframes_t worst_input_latency () const { return _worst_input_latency; }
- 	nframes_t worst_track_latency () const { return _worst_track_latency; }
-+	nframes_t worst_playback_latency () const { return _worst_output_latency + _worst_track_latency; }
- 
- 	int save_state (string snapshot_name, bool pending = false, bool switch_to_snapshot = false);
- 	int restore_state (string snapshot_name);
-diff --git a/libs/ardour/ardour/types.h b/libs/ardour/ardour/types.h
-index 84c4d0c..bfc22a4 100644
---- a/libs/ardour/ardour/types.h
-+++ b/libs/ardour/ardour/types.h
-@@ -20,10 +20,6 @@
- #ifndef __ardour_types_h__
- #define __ardour_types_h__
- 
--#ifndef __STDC_FORMAT_MACROS
--#define __STDC_FORMAT_MACROS /* PRI<foo>; C++ requires explicit requesting of these */
--#endif
--
- #include <istream>
- #include <vector>
- #include <boost/shared_ptr.hpp>
-diff --git a/libs/ardour/audio_diskstream.cc b/libs/ardour/audio_diskstream.cc
-index 2c87773..4a37c70 100644
---- a/libs/ardour/audio_diskstream.cc
-+++ b/libs/ardour/audio_diskstream.cc
-@@ -397,6 +397,8 @@ AudioDiskstream::check_record_status (nframes_t transport_frame, nframes_t nfram
- 	possibly_recording = (rolling << 2) | (record_enabled() << 1) | can_record;
- 	change = possibly_recording ^ last_possibly_recording;
- 
-+        nframes_t existing_material_offset = _session.worst_playback_latency ();
-+
-         if (possibly_recording == fully_rec_enabled) {
- 
-                 if (last_possibly_recording == fully_rec_enabled) {
-@@ -405,65 +407,12 @@ AudioDiskstream::check_record_status (nframes_t transport_frame, nframes_t nfram
- 
-                 /* we transitioned to recording. lets see if its transport based or a punch */
-                 
--		first_recordable_frame = transport_frame + _capture_offset;
-+		capture_start_frame = _session.transport_frame();
-+		first_recordable_frame = capture_start_frame + _capture_offset;
- 		last_recordable_frame = max_frames;
--		capture_start_frame = transport_frame;
--
--                if (change & transport_rolling) {
--
--                        /* transport-change (started rolling) */
--                        
--			if (_alignment_style == ExistingMaterial) {
--                                
--                                /* there are two delays happening:
--                                   
--                                   1) inbound, represented by _capture_offset
--                                   2) outbound, represented by _session.worst_output_latency()
--
--                                   the first sample to record occurs when the larger of these
--                                   two has elapsed, since they occur in parallel.
--
--                                   since we've already added _capture_offset, just add the
--                                   difference if _session.worst_output_latency() is larger.
--                                */
--
--                                if (_capture_offset < _session.worst_output_latency()) {
--                                        first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
--                                } 
--                        } else {
--				first_recordable_frame += _roll_delay;
--  			}
--                        
--                } else {
- 
--                        /* punch in */
--
--			if (_alignment_style == ExistingMaterial) {
--
--				/* There are two kinds of punch:
--                                   
--                                   manual punch in happens at the correct transport frame
--                                   because the user hit a button. but to get alignment correct 
--                                   we have to back up the position of the new region to the 
--                                   appropriate spot given the roll delay.
--
--                                   autopunch toggles recording at the precise
--				   transport frame, and then the DS waits
--				   to start recording for a time that depends
--				   on the output latency.
--
--                                   XXX: BUT THIS CODE DOESN'T DIFFERENTIATE !!!
--
--				*/
--
--                                if (_capture_offset < _session.worst_output_latency()) {
--                                        /* see comment in ExistingMaterial block above */
--                                        first_recordable_frame += (_session.worst_output_latency() - _capture_offset);
--                                }
--
--			} else {
--				capture_start_frame -= _roll_delay;
--			}
-+                if (_alignment_style == ExistingMaterial) {
-+                        first_recordable_frame += existing_material_offset;
-                 }
- 
- 		if (recordable() && destructive()) {
-@@ -499,14 +448,10 @@ AudioDiskstream::check_record_status (nframes_t transport_frame, nframes_t nfram
-                         } else {
-                                 /* punch out */
-                                 
--                                last_recordable_frame = transport_frame + _capture_offset;
-+                                last_recordable_frame = _session.transport_frame() + _capture_offset;
-                                 
-                                 if (_alignment_style == ExistingMaterial) {
--                                        if (_session.worst_output_latency() > _capture_offset) {
--                                                last_recordable_frame += (_session.worst_output_latency() - _capture_offset);
--                                        }
--                                } else {
--                                        last_recordable_frame += _roll_delay;
-+                                        last_recordable_frame += existing_material_offset;
-                                 }
-                         }
-                 }
-diff --git a/libs/ardour/audio_playlist.cc b/libs/ardour/audio_playlist.cc
-index 9c331af..f5f275b 100644
---- a/libs/ardour/audio_playlist.cc
-+++ b/libs/ardour/audio_playlist.cc
-@@ -26,6 +26,7 @@
- #include <ardour/types.h>
- #include <ardour/configuration.h>
- #include <ardour/audioplaylist.h>
-+#include <ardour/region_factory.h>
- #include <ardour/audioregion.h>
- #include <ardour/crossfade.h>
- #include <ardour/crossfade_compare.h>
-@@ -96,6 +97,93 @@ AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, stri
- AudioPlaylist::AudioPlaylist (boost::shared_ptr<const AudioPlaylist> other, nframes_t start, nframes_t cnt, string name, bool hidden)
- 	: Playlist (other, start, cnt, name, hidden)
- {
-+	clear();  //we need to remove any regions that the parent constructor added
-+	
-+	RegionLock rlock2 (const_cast<AudioPlaylist*> (other.get()));
-+
-+	nframes_t end = start + cnt - 1;
-+
-+	Playlist::init (hidden);
-+
-+	in_set_state++;
-+
-+	//now re-add the regions with the correct fade in/out
-+	for (RegionList::const_iterator i = other->regions.begin(); i != other->regions.end(); i++) {
-+
-+		boost::shared_ptr<AudioRegion> region = boost::dynamic_pointer_cast<AudioRegion> (*i);
-+		boost::shared_ptr<AudioRegion> new_region;
-+		nframes64_t offset = 0;
-+		nframes64_t trim = 0;
-+		nframes64_t position = 0;
-+		nframes64_t len = 0;
-+		string    new_name;
-+		OverlapType overlap;
-+		
-+		nframes_t fade_in_len = 64;
-+		nframes_t fade_out_len = 64;
-+
-+		overlap = region->coverage (start, end+1);
-+
-+		switch (overlap) {
-+		case OverlapNone:
-+			continue;
-+
-+		case OverlapInternal:
-+			offset = start - region->position();
-+			trim = region->last_frame() -end;
-+			position = 0;
-+			len = cnt;
-+			if (region->fade_in().back()->when > offset)
-+				fade_in_len = region->fade_in().back()->when - offset;
-+			if (region->fade_out().back()->when > trim)
-+				fade_out_len = region->fade_out().back()->when - trim;
-+			break;
-+
-+		case OverlapStart:
-+			offset = 0;
-+			position = region->position() - start;
-+			len = end - region->position();
-+			if (region->fade_in().back()->when > offset)
-+				fade_in_len = region->fade_in().back()->when - offset;
-+			if (start > region->last_frame() - region->fade_out().back()->when)
-+				fade_out_len = region->last_frame() - start;
-+			break;
-+
-+		case OverlapEnd:
-+			offset = start - region->position();
-+			trim = region->last_frame() -end;
-+			position = 0;
-+			len = region->length() - offset;
-+			if (region->fade_in().back()->when > offset)
-+				fade_in_len = region->fade_in().back()->when - offset;
-+			if (start > region->last_frame() - region->fade_out().back()->when)
-+				fade_out_len = region->last_frame() - start;
-+			else 
-+				fade_out_len = region->fade_out().back()->when;
-+			break;
-+
-+		case OverlapExternal:
-+			offset = 0;
-+			trim = region->last_frame() -end;
-+			position = region->position() - start;
-+			len = region->length();
-+			fade_in_len = region->fade_in().back()->when;
-+			fade_out_len = region->fade_out().back()->when;
-+			break;
-+		}
-+
-+		_session.region_name (new_name, region->name(), false);
-+
-+		new_region = boost::dynamic_pointer_cast<AudioRegion> (RegionFactory::RegionFactory::create (region, offset, len, new_name, region->layer(), region->flags()));
-+		new_region->set_fade_in_length(fade_in_len > 64 ? fade_in_len : 64);
-+		new_region->set_fade_out_length(fade_out_len > 64 ? fade_out_len : 64);
-+
-+		add_region_internal (new_region, position);
-+	}
-+	
-+	in_set_state--;
-+	first_set_state = false;
-+
- 	/* this constructor does NOT notify others (session) */
- }
- 
-diff --git a/libs/ardour/audio_unit.cc b/libs/ardour/audio_unit.cc
-index f6a6c15..10a8568 100644
---- a/libs/ardour/audio_unit.cc
-+++ b/libs/ardour/audio_unit.cc
-@@ -47,8 +47,6 @@
- 
- #include <CoreFoundation/CoreFoundation.h>
- #include <CoreServices/CoreServices.h>
--#include <AudioUnit/AudioUnit.h>
--#include <AudioToolbox/AudioUnitUtilities.h>
- 
- #include "i18n.h"
- 
-@@ -355,6 +353,8 @@ AUPlugin::AUPlugin (AudioEngine& engine, Session& session, boost::shared_ptr<CAC
- 	, current_offset (0)
- 	, current_buffers (0)
- 	, frames_processed (0)
-+	, _parameter_listener (0)
-+	, _parameter_listener_arg (0)
- 	, last_transport_rolling (false)
- 	, last_transport_speed (0.0)
- {			
-@@ -382,13 +382,21 @@ AUPlugin::AUPlugin (const AUPlugin& other)
- 	, current_offset (0)
- 	, current_buffers (0)
- 	, frames_processed (0)
--	  
-+	, _parameter_listener (0)
-+	, _parameter_listener_arg (0)
-+	, last_transport_rolling (false)
-+	, last_transport_speed (0.0)
- {
- 	init ();
- }
- 
- AUPlugin::~AUPlugin ()
- {
-+	if (_parameter_listener) {
-+		AUListenerDispose (_parameter_listener);
-+		_parameter_listener = 0;
-+	}
-+	
- 	if (unit) {
- 		TRACE_API ("about to call uninitialize in plugin destructor\n");
- 		unit->Uninitialize ();
-@@ -446,17 +454,26 @@ AUPlugin::init ()
- 		throw failed_constructor ();
- 	}
- 	
--	AURenderCallbackStruct renderCallbackInfo;
--
--	renderCallbackInfo.inputProc = _render_callback;
--	renderCallbackInfo.inputProcRefCon = this;
-+	TRACE_API ("count global elements\n");
-+	unit->GetElementCount (kAudioUnitScope_Global, global_elements);
-+	TRACE_API ("count input elements\n");
-+	unit->GetElementCount (kAudioUnitScope_Input, input_elements);
-+	TRACE_API ("count output elements\n");
-+	unit->GetElementCount (kAudioUnitScope_Output, output_elements);
- 
--	TRACE_API ("set render callback in input scope\n");
--	if ((err = unit->SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 
--					 0, (void*) &renderCallbackInfo, sizeof(renderCallbackInfo))) != 0) {
--		cerr << "cannot install render callback (err = " << err << ')' << endl;
--		throw failed_constructor();
--	}
-+        if (input_elements > 0) {
-+                AURenderCallbackStruct renderCallbackInfo;
-+                
-+                renderCallbackInfo.inputProc = _render_callback;
-+                renderCallbackInfo.inputProcRefCon = this;
-+                
-+                TRACE_API ("set render callback in input scope\n");
-+                if ((err = unit->SetProperty (kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Input, 
-+                                              0, (void*) &renderCallbackInfo, sizeof(renderCallbackInfo))) != 0) {
-+                        cerr << "cannot install render callback (err = " << err << ')' << endl;
-+                        throw failed_constructor();
-+                }
-+        }
- 
- 	/* tell the plugin about tempo/meter/transport callbacks in case it wants them */
- 
-@@ -475,13 +492,6 @@ AUPlugin::init ()
- 			   &info,
- 			   sizeof (HostCallbackInfo));
- 
--	TRACE_API ("count global elements\n");
--	unit->GetElementCount (kAudioUnitScope_Global, global_elements);
--	TRACE_API ("count input elements\n");
--	unit->GetElementCount (kAudioUnitScope_Input, input_elements);
--	TRACE_API ("count output elements\n");
--	unit->GetElementCount (kAudioUnitScope_Output, output_elements);
--
- 	/* these keep track of *configured* channel set up,
- 	   not potential set ups.
- 	*/
-@@ -494,6 +504,7 @@ AUPlugin::init ()
- 		throw failed_constructor();
- 	}
- 
-+	create_parameter_listener (AUPlugin::_parameter_change_listener, this, 0.05);
- 	discover_parameters ();
- 	discover_factory_presets ();
- 
-@@ -609,11 +620,14 @@ AUPlugin::discover_parameters ()
- 			d.max_unbound = 0; // upper is bound
- 
- 			descriptors.push_back (d);
-+
-+			uint32_t last_param = descriptors.size() - 1;
-+			parameter_map.insert (pair<uint32_t,uint32_t> (d.id, last_param));
-+			listen_to_parameter (last_param);
- 		}
- 	}
- }
- 
--
- static unsigned int
- four_ints_to_four_byte_literal (unsigned char n[4])
- {
-@@ -757,24 +771,34 @@ AUPlugin::latency () const
- void
- AUPlugin::set_parameter (uint32_t which, float val)
- {
--	if (which < descriptors.size()) {
--		const AUParameterDescriptor& d (descriptors[which]);
--		TRACE_API ("set parameter %d in scope %d element %d to %f\n", d.id, d.scope, d.element, val);
--		unit->SetParameter (d.id, d.scope, d.element, val);
-+	if (which >= descriptors.size()) {
-+		return;
-+	}
- 
--		/* tell the world what we did */
-+	const AUParameterDescriptor& d (descriptors[which]);
-+	TRACE_API ("set parameter %d in scope %d element %d to %f\n", d.id, d.scope, d.element, val);
-+	unit->SetParameter (d.id, d.scope, d.element, val);
-+	
-+	/* tell the world what we did */
-+	
-+	AudioUnitEvent theEvent;
-+	
-+	theEvent.mEventType = kAudioUnitEvent_ParameterValueChange;
-+	theEvent.mArgument.mParameter.mAudioUnit = unit->AU();
-+	theEvent.mArgument.mParameter.mParameterID = d.id;
-+	theEvent.mArgument.mParameter.mScope = d.scope;
-+	theEvent.mArgument.mParameter.mElement = d.element;
-+	
-+	TRACE_API ("notify about parameter change\n");
- 
--		AudioUnitEvent theEvent;
--		
--		theEvent.mEventType = kAudioUnitEvent_ParameterValueChange;
--		theEvent.mArgument.mParameter.mAudioUnit = unit->AU();
--		theEvent.mArgument.mParameter.mParameterID = d.id;
--		theEvent.mArgument.mParameter.mScope = d.scope;
--		theEvent.mArgument.mParameter.mElement = d.element;
-+	/* use the AU Event API to notify about the change. Our own listener will 
-+	   end up "emitting" ParameterChanged, and this way ParameterChanged is 
-+	   used whether the change to the parameter comes from this function
-+	   or within the plugin or anywhere else, since they should all notify
-+	   via AUEventListenerNotify().
-+	*/
- 
--		TRACE_API ("notify about parameter change\n");
--		AUEventListenerNotify (NULL, NULL, &theEvent);
--	}
-+	AUEventListenerNotify (NULL, NULL, &theEvent);
- }
- 
- float
-@@ -2464,3 +2488,77 @@ AUPluginInfo::stringify_descriptor (const CAComponentDescription& desc)
- 	return s.str();
- }
- 
-+int
-+AUPlugin::create_parameter_listener (AUEventListenerProc cb, void* arg, float interval_secs)
-+{
-+	CFRunLoopRef run_loop = (CFRunLoopRef) GetCFRunLoopFromEventLoop(GetCurrentEventLoop()); 
-+	CFStringRef  loop_mode = kCFRunLoopDefaultMode;
-+
-+	if (AUEventListenerCreate (cb, arg, run_loop, loop_mode, interval_secs, interval_secs, &_parameter_listener) != noErr) {
-+		return -1;
-+	}
-+
-+	_parameter_listener_arg = arg;
-+
-+	return 0;
-+}
-+
-+int
-+AUPlugin::listen_to_parameter (uint32_t param_id)
-+{
-+	AudioUnitEvent      event;
-+
-+	if (!_parameter_listener || param_id >= descriptors.size()) {
-+		return -2;
-+	}
-+
-+	event.mEventType = kAudioUnitEvent_ParameterValueChange;
-+	event.mArgument.mParameter.mAudioUnit = unit->AU();
-+	event.mArgument.mParameter.mParameterID = descriptors[param_id].id;
-+	event.mArgument.mParameter.mScope = descriptors[param_id].scope;
-+	event.mArgument.mParameter.mElement = descriptors[param_id].element;
-+
-+	if (AUEventListenerAddEventType (_parameter_listener, _parameter_listener_arg, &event) != noErr) {
-+		return -1;
-+	} 
-+
-+	return 0;
-+}
-+
-+int
-+AUPlugin::end_listen_to_parameter (uint32_t param_id)
-+{
-+	AudioUnitEvent      event;
-+
-+	if (!_parameter_listener || param_id >= descriptors.size()) {
-+		return -2;
-+	}
-+
-+	event.mEventType = kAudioUnitEvent_ParameterValueChange;
-+	event.mArgument.mParameter.mAudioUnit = unit->AU();
-+	event.mArgument.mParameter.mParameterID = descriptors[param_id].id;
-+	event.mArgument.mParameter.mScope = descriptors[param_id].scope;
-+	event.mArgument.mParameter.mElement = descriptors[param_id].element;
-+
-+	if (AUEventListenerRemoveEventType (_parameter_listener, _parameter_listener_arg, &event) != noErr) {
-+		return -1;
-+	} 
-+
-+	return 0;
-+}
-+
-+void
-+AUPlugin::_parameter_change_listener (void* arg, void* src, const AudioUnitEvent* event, UInt64 host_time, Float32 new_value)
-+{
-+	((AUPlugin*) arg)->parameter_change_listener (arg, src, event, host_time, new_value);
-+}
-+
-+void
-+AUPlugin::parameter_change_listener (void* /*arg*/, void* /*src*/, const AudioUnitEvent* event, UInt64 host_time, Float32 new_value)
-+{
-+	ParameterMap::iterator i = parameter_map.find (event->mArgument.mParameter.mParameterID);
-+
-+	if (i != parameter_map.end()) {
-+		ParameterChanged (i->second, new_value);
-+	}
-+}
-diff --git a/libs/ardour/audioengine.cc b/libs/ardour/audioengine.cc
-index 802cbab..6949dec 100644
---- a/libs/ardour/audioengine.cc
-+++ b/libs/ardour/audioengine.cc
-@@ -22,9 +22,12 @@
- #include <vector>
- #include <sstream>
- 
-+#include <boost/scoped_ptr.hpp>
-+
- #include <glibmm/timer.h>
- #include <pbd/pthread_utils.h>
- #include <pbd/stacktrace.h>
-+#include <pbd/epa.h>
- 
- #include <ardour/audioengine.h>
- #include <ardour/buffer.h>
-@@ -332,7 +335,10 @@ AudioEngine::process_callback (nframes_t nframes)
- 
- 	IO::CycleStart (nframes);
- 
--	if (_freewheeling) {
-+	/* test if we are freewheeling and there are freewheel signals connected.
-+           ardour should act normally even when freewheeling unless /it/ is exporting */
-+
-+	if (_freewheeling && !Freewheel.empty()) {
- 		if (Freewheel (nframes)) {
- 			jack_set_freewheel (_priv_jack, false);
- 		}
-@@ -667,7 +673,7 @@ int
- AudioEngine::connect (const string& source, const string& destination)
- {
-         GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
--	
-+
- 	string s = make_port_name_non_relative (source);
- 	string d = make_port_name_non_relative (destination);
- 
-@@ -1116,10 +1122,20 @@ AudioEngine::remove_connections_for (Port* port)
- int
- AudioEngine::connect_to_jack (string client_name)
- {
-+        EnvironmentalProtectionAgency* global_epa = EnvironmentalProtectionAgency::get_global_epa ();
-+        boost::scoped_ptr<EnvironmentalProtectionAgency> current_epa;
- 	jack_options_t options = JackNullOption;
- 	jack_status_t status;
- 	const char *server_name = NULL;
- 
-+        /* revert all environment settings back to whatever they were when ardour started
-+         */
-+
-+        if (global_epa) {
-+                current_epa.reset (new EnvironmentalProtectionAgency(true)); /* will restore settings when we leave scope */
-+                global_epa->restore ();
-+        }
-+
- 	jack_client_name = client_name; /* might be reset below */
- 	_jack = jack_client_open (jack_client_name.c_str(), options, &status, server_name);
- 
-@@ -1276,7 +1292,7 @@ AudioEngine::reconnect_to_jack ()
- 			error << string_compose (_("Disconnected from JACK while reconnecting. You should quit %1 now."), PROGRAM_NAME) << endmsg;
- 			return -1;
- 		}
--		
-+
- 		if ((err = jack_connect (_priv_jack, (*i).first.c_str(), (*i).second.c_str())) != 0) {
- 			if (err != EEXIST) {
- 				error << string_compose (_("could not reconnect %1 and %2 (err = %3)"),
-diff --git a/libs/ardour/audiofilesource.cc b/libs/ardour/audiofilesource.cc
-index 9141456..ba5ab8a 100644
---- a/libs/ardour/audiofilesource.cc
-+++ b/libs/ardour/audiofilesource.cc
-@@ -96,6 +96,7 @@ AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags)
- 		throw failed_constructor ();
- 	}
- 
-+        prevent_deletion ();
- 	fix_writable_flags ();
- }
- 
-@@ -110,6 +111,7 @@ AudioFileSource::AudioFileSource (Session& s, ustring path, Flag flags, SampleFo
- 		throw failed_constructor ();
- 	}
- 
-+        prevent_deletion ();
- 	fix_writable_flags ();
- }
- 
-@@ -129,6 +131,7 @@ AudioFileSource::AudioFileSource (Session& s, const XMLNode& node, bool must_exi
- 		throw failed_constructor ();
- 	}
- 
-+        prevent_deletion ();
- 	fix_writable_flags ();
- }
- 
-@@ -141,8 +144,25 @@ AudioFileSource::~AudioFileSource ()
- }
- 
- void
-+AudioFileSource::prevent_deletion ()
-+{
-+        /* if this file already exists, it cannot be removed, ever
-+         */
-+
-+        if (Glib::file_test (_path, Glib::FILE_TEST_EXISTS)) {
-+                if (!(_flags & Destructive)) {
-+                        mark_immutable ();
-+                } else {
-+                        _flags = Flag (_flags & ~(Removable|RemovableIfEmpty|RemoveAtDestroy));
-+                }
-+        }
-+}
-+
-+void
- AudioFileSource::fix_writable_flags ()
- {
-+        /* if the session is not writable, neither is this file 
-+         */
- 	if (!_session.writable()) {
- 		_flags = Flag (_flags & ~(Writable|Removable|RemovableIfEmpty|RemoveAtDestroy|CanRename));
- 	}
-@@ -354,6 +374,7 @@ AudioFileSource::mark_for_remove ()
- 	}
- 
- 	_flags = Flag (_flags | Removable | RemoveAtDestroy);
-+
- }
- 
- void
-@@ -466,6 +487,7 @@ AudioFileSource::move_to_trash (const ustring& trash_dir_name)
- 
- 	_flags = Flag (_flags & ~(RemoveAtDestroy|Removable|RemovableIfEmpty));
- 
-+
- 	return 0;
- }
- 
-@@ -775,7 +797,6 @@ AudioFileSource::mark_immutable ()
- 	}
- }
- 
--
- Sample*
- AudioFileSource::get_interleave_buffer (nframes_t size)
- {
-diff --git a/libs/ardour/audioregion.cc b/libs/ardour/audioregion.cc
-index 7130e52..1da2d1e 100644
---- a/libs/ardour/audioregion.cc
-+++ b/libs/ardour/audioregion.cc
-@@ -735,7 +735,7 @@ AudioRegion::state (bool full)
- 			child->add_child_nocopy (_fade_in.get_state ());
- 		}
- 
--		child->add_property (X_("active"), _fade_in_disabled ? X_("no") : X_("yes"));
-+		child->add_property (X_("active"), (_flags & FadeIn) ? X_("yes") : X_("no"));
- 		
- 		child = node.add_child (X_("FadeOut"));
- 		
-@@ -745,7 +745,7 @@ AudioRegion::state (bool full)
- 			child->add_child_nocopy (_fade_out.get_state ());
- 		}
- 		
--		child->add_property (X_("active"), _fade_out_disabled ? X_("no") : X_("yes"));
-+		child->add_property (X_("active"), (_flags & FadeOut) ? X_("yes") : X_("no"));
- 	}
- 	
- 	child = node.add_child ("Envelope");
-diff --git a/libs/ardour/automation_event.cc b/libs/ardour/automation_event.cc
-index dd2930a..2f35fa3 100644
---- a/libs/ardour/automation_event.cc
-+++ b/libs/ardour/automation_event.cc
-@@ -248,7 +248,7 @@ AutomationList::start_touch (double when)
- }
- 
- void
--AutomationList::stop_touch (bool mark, double when)
-+AutomationList::stop_touch (bool mark, double when, double value)
- {
- 	g_atomic_int_set (&_touching, 0);
- 
-@@ -268,6 +268,11 @@ AutomationList::stop_touch (bool mark, double when)
-                         delete ninfo;
-                 }
-         }
-+        
-+	//if no automation yet
-+    if (events.empty()) {
-+		default_value = value;
-+	}
- }
- 
- void
-@@ -313,12 +318,30 @@ void AutomationList::_x_scale (double factor)
- void
- AutomationList::write_pass_finished (double when)
- {
--        merge_nascent (when);
-+	//if fader is in Write, we need to put an automation point to mark the last place we rolled.
-+	if ( (_state & Auto_Write) ) {
-+		if ( !nascent.empty() && !nascent.back()->events.empty() ) {
-+			rt_add( when, nascent.back()->events.back()->value );
-+		}
-+	}
-+
-+    merge_nascent (when);
- }
- 
- void
- AutomationList::rt_add (double when, double value)
- {
-+	//for now, automation only writes during forward motion
-+	//if transport goes in reverse, start a new nascent pass and ignore this change
-+	float last_when = 0;
-+	if (!nascent.back()->events.empty())
-+		last_when = nascent.back()->events.back()->when;
-+	if ( (when < last_when) ) {
-+		Glib::Mutex::Lock lm (lock);
-+		nascent.push_back (new NascentInfo (false));
-+		return;
-+	}
-+	
- 	/* this is for automation recording */
- 
- 	if ((_state & Auto_Touch) && !touching()) {
-@@ -329,10 +352,11 @@ AutomationList::rt_add (double when, double value)
- 
-         if (lm.locked()) {
-                 assert (!nascent.empty());
--                if (!nascent.back()->events.empty()) {
--                        assert (when > nascent.back()->events.back()->when);
--                }
--                nascent.back()->events.push_back (point_factory (when, value));
-+                if (nascent.back()->events.empty() ){
-+ 					nascent.back()->events.push_back (point_factory (when, value));
-+				} else if (when > nascent.back()->events.back()->when) {
-+					nascent.back()->events.push_back (point_factory (when, value));
-+                 }
-         }
- }
- 
-@@ -346,14 +370,48 @@ AutomationList::merge_nascent (double when)
-                         return;
-                 }
- 
--                for (list<NascentInfo*>::iterator n = nascent.begin(); n != nascent.end(); ++n) {
-+               //thin automation data in each nascent packet
-+				for (list<NascentInfo*>::iterator n = nascent.begin(); n != nascent.end(); ++n) {
-+					ControlEvent *next = NULL;
-+					ControlEvent *cur = NULL;
-+					ControlEvent *prev = NULL;
-+					int counter = 0;
-+					AutomationEventList delete_list;
-+					for (AutomationEventList::iterator x = (*n)->events.begin(); x != (*n)->events.end(); x++) {
-+						next = *x;
-+						counter++;
-+						if (counter > 2) {  //wait for the third iteration so "cur" & "prev" are initialized
-+	
-+							float area = fabs(
-+								0.5 * (
-+								prev->when*(cur->value - next->value) + 
-+								cur->when*(next->value - prev->value) + 
-+								next->when*(prev->value - cur->value) ) 
-+							);
-+							 
-+//printf( "area: %3.16f\n", area);
-+							if (area < ( Config->get_automation_thinning_strength() ) )
-+								delete_list.push_back(cur);
-+						}
-+						prev = cur;
-+						cur = next;
-+					}
-+					
-+					for (AutomationEventList::iterator x = delete_list.begin(); x != delete_list.end(); ++x) {
-+						(*n)->events.remove(*x);
-+						delete *x;
-+					}
-+					
-+				}
-+				
-+				for (list<NascentInfo*>::iterator n = nascent.begin(); n != nascent.end(); ++n) {
- 
-                         NascentInfo* ninfo = *n;
-                         AutomationEventList& nascent_events (ninfo->events);
-                         bool need_adjacent_start_clamp;
-                         bool need_adjacent_end_clamp;
- 
--                        if (nascent_events.empty()) {
-+                        if (nascent_events.size() < 2) {
-                                 delete ninfo;
-                                 continue;
-                         }
-@@ -363,27 +421,15 @@ AutomationList::merge_nascent (double when)
-                         }
-                         
-                         if (ninfo->end_time < 0.0) {
--                                ninfo->end_time = when;
-+                                ninfo->end_time = nascent_events.back()->when;
-                         }
- 
--                        bool preexisting = !events.empty();
-+						bool preexisting = !events.empty();
- 
-                         if (!preexisting) {
-                                 
-                                 events = nascent_events;
-                                 
--                        } else if (ninfo->end_time < events.front()->when) {
--                                
--                                /* all points in nascent are before the first existing point */
--
--                                events.insert (events.begin(), nascent_events.begin(), nascent_events.end());
--                                
--                        } else if (ninfo->start_time > events.back()->when) {
--                                
--                                /* all points in nascent are after the last existing point */
--
--                                events.insert (events.end(), nascent_events.begin(), nascent_events.end());
--                                
-                         } else {
-                                 
-                                 /* find the range that overaps with nascent events,
-@@ -393,7 +439,7 @@ AutomationList::merge_nascent (double when)
-                                 iterator i;
-                                 iterator range_begin = events.end();
-                                 iterator range_end = events.end();
--                                double end_value = unlocked_eval (ninfo->end_time);
-+                                double end_value = unlocked_eval (ninfo->end_time + 1);
-                                 double start_value = unlocked_eval (ninfo->start_time - 1);
- 
-                                 need_adjacent_end_clamp = true;
-@@ -435,25 +481,25 @@ AutomationList::merge_nascent (double when)
-                                                 }
-                                         }
-                                 }
--                                
--                                assert (range_begin != events.end());
--                                
--                                if (range_begin != events.begin()) {
--                                        /* clamp point before */
--                                        if (need_adjacent_start_clamp) {
--                                                events.insert (range_begin, point_factory (ninfo->start_time, start_value));
--                                        }
--                                }
--
--                                events.insert (range_begin, nascent_events.begin(), nascent_events.end());
--
--                                if (range_end != events.end()) {
--                                        /* clamp point after */
--                                        if (need_adjacent_end_clamp) {
--                                                events.insert (range_begin, point_factory (ninfo->end_time, end_value));
--                                        }
--                                }
--                                
-+ 
-+								//if you write past the end of existing automation,
-+								//then treat it as virgin territory
-+                                if (range_end == events.end()) {
-+									need_adjacent_end_clamp = false;
-+								}
-+
-+								/* clamp point before */
-+								if (need_adjacent_start_clamp) {
-+									   events.insert (range_begin, point_factory (ninfo->start_time-1, start_value));
-+								}
-+
-+								events.insert (range_begin, nascent_events.begin(), nascent_events.end());
-+
-+								/* clamp point after */
-+								if (need_adjacent_end_clamp) {
-+									   events.insert (range_begin, point_factory (ninfo->end_time+1, end_value));
-+								}
-+						
-                                 events.erase (range_begin, range_end);
-                         }
- 
-@@ -474,7 +520,8 @@ void
- AutomationList::fast_simple_add (double when, double value)
- {
- 	/* to be used only for loading pre-sorted data from saved state */
--	events.insert (events.end(), point_factory (when, value));
-+	if ( events.empty() || (when > events.back()->when) ) 	
-+		events.insert (events.end(), point_factory (when, value));
- }
- 
- void
-@@ -983,12 +1030,7 @@ AutomationList::shared_eval (double x)
- 		return default_value;
- 
- 	case 1:
--		if (x >= events.front()->when) {
--			return events.front()->value;
--		} else {
--			// return default_value;
--			return events.front()->value;
--		} 
-+		return events.front()->value;
- 		
- 	case 2:
- 		if (x >= events.back()->when) {
-@@ -1022,7 +1064,7 @@ AutomationList::shared_eval (double x)
- 			return events.front()->value;
- 		}
- 
--		return multipoint_eval (x);
-+		return AutomationList::multipoint_eval (x);  //switch to plain linear for now.
- 		break;
- 	}
- 
-diff --git a/libs/ardour/coreaudiosource.cc b/libs/ardour/coreaudiosource.cc
-index a6aceb7..5a3c542 100644
---- a/libs/ardour/coreaudiosource.cc
-+++ b/libs/ardour/coreaudiosource.cc
-@@ -19,7 +19,6 @@
- */
- 
- #include <algorithm>
--#define __STDC_FORMAT_MACROS
- #include <inttypes.h>
- 
- #include <pbd/error.h>
-@@ -268,7 +267,7 @@ CoreAudioSource::get_soundfile_info (string path, SoundFileInfo& _info, string&
- 		}
- 		
- 		char buf[32];
--		snprintf (buf, sizeof (buf), " %" PRIu32 " bit", absd.mBitsPerChannel);
-+		snprintf (buf, sizeof (buf), " %" PRIu32 " bit", (uint32_t) absd.mBitsPerChannel);
- 		_info.format_name += buf;
- 		_info.format_name += '\n';
- 		
-diff --git a/libs/ardour/crossfade.cc b/libs/ardour/crossfade.cc
-index 41737b1..8340b8b 100644
---- a/libs/ardour/crossfade.cc
-+++ b/libs/ardour/crossfade.cc
-@@ -711,10 +711,13 @@ Crossfade::set_state (const XMLNode& node)
- 	nframes_t val;
- 
- 	if ((prop = node.property ("position")) != 0) {
--		sscanf (prop->value().c_str(), "%" PRIu32, &val);
--		if (val != _position) {
--			_position = val;
--			what_changed = Change (what_changed | PositionChanged);
-+		if (sscanf (prop->value().c_str(), "%" PRIu32, &val) == 1) {
-+			if (val != _position) {
-+				_position = val;
-+				what_changed = Change (what_changed | PositionChanged);
-+			}
-+		} else {
-+			warning << _("can't read value from crossfade position property") << endmsg;
- 		}
- 	} else {
- 		warning << _("old-style crossfade information - no position information") << endmsg;
-@@ -751,12 +754,14 @@ Crossfade::set_state (const XMLNode& node)
- 
- 	if ((prop = node.property ("length")) != 0) {
- 
--		sscanf (prop->value().c_str(), "%" PRIu32, &val);
--		if (val != _length) {
--			_length = atol (prop->value().c_str());
--			what_changed = Change (what_changed | LengthChanged);
-+		if (sscanf (prop->value().c_str(), "%" PRIu32, &val) == 1) {
-+			if (val != _length) {
-+				_length = atol (prop->value().c_str());
-+				what_changed = Change (what_changed | LengthChanged);
-+			}
-+		} else {
-+			warning << _("can't read value from crossfade length property") << endmsg;		
- 		}
--
- 	} else {
- 		
- 		/* XXX this branch is legacy code from before
-@@ -798,6 +803,11 @@ Crossfade::set_state (const XMLNode& node)
- 		}
- 	}
- 
-+        if (_fade_in.size() < 2) {
-+                cerr << "Fade in data missing any points! Crossfade will be lost!\n";
-+                return -1;
-+        }
-+
- 	_fade_in.front()->value=0.0;
- 	_fade_in.back()->value=1.0;
- 
-@@ -826,6 +836,11 @@ Crossfade::set_state (const XMLNode& node)
- 		}
- 	}
- 
-+        if (_fade_out.size() < 2) {
-+                cerr << "Fade out data missing any points! Crossfade will be lost!\n";
-+                return -1;
-+        }
-+
- 	_fade_out.front()->value=1.0;
- 	_fade_out.back()->value=0.0;
- 
-diff --git a/libs/ardour/curve.cc b/libs/ardour/curve.cc
-index f2ab337..94b6ed8 100644
---- a/libs/ardour/curve.cc
-+++ b/libs/ardour/curve.cc
-@@ -312,7 +312,7 @@ Curve::_get_vector (double x0, double x1, float *vec, int64_t veclen)
- 		return;
- 	}
- 
-- 	if (npoints == 1 ) {
-+ 	if (npoints == 1) {
-  	
-  		for (i = 0; i < veclen; ++i) {
-  			vec[i] = events.front()->value;
-@@ -355,17 +355,18 @@ Curve::_get_vector (double x0, double x1, float *vec, int64_t veclen)
- 
- 	rx = lx;
- 
-+	/* note: if there are veclen elements in the output,
-+	   there are only veclen-1 steps between them.
-+	*/
-+	
- 	if (veclen > 1) {
--
--		/* note: if there are veclen elements in the output,
--		   there are only veclen-1 steps between them.
--		*/
--
- 		dx = (hx - lx) / (veclen-1);
--
--		for (i = 0; i < veclen; ++i, rx += dx) {
--			vec[i] = multipoint_eval (rx);
--		}
-+	} else {
-+		dx = 0;
-+	}
-+	
-+	for (i = 0; i < veclen; ++i, rx += dx) {
-+		vec[i] = multipoint_eval (rx);
- 	}
- }
- 
-diff --git a/libs/ardour/enums.cc b/libs/ardour/enums.cc
-index 395f1ac..6605fc2 100644
---- a/libs/ardour/enums.cc
-+++ b/libs/ardour/enums.cc
-@@ -31,7 +31,8 @@
- 
- using namespace std;
- using namespace PBD;
--using namespace ARDOUR;
-+namespace ARDOUR
-+{
- 
- void
- setup_enum_writer ()
-@@ -147,6 +148,7 @@ setup_enum_writer ()
- 
- 	REGISTER_ENUM (Slide);
- 	REGISTER_ENUM (Splice);	
-+	REGISTER_ENUM (Lock);	
- 	REGISTER (_EditMode);
- 
- 	REGISTER_ENUM (Start);
-@@ -362,3 +364,5 @@ setup_enum_writer ()
- 	REGISTER (_Track_FreezeState);
- 	
- }
-+
-+}
-diff --git a/libs/ardour/io.cc b/libs/ardour/io.cc
-index 21f51e6..be03df7 100644
---- a/libs/ardour/io.cc
-+++ b/libs/ardour/io.cc
-@@ -260,7 +260,7 @@ IO::apply_declick (vector<Sample *>& bufs, uint32_t nbufs, nframes_t nframes, ga
- 
- 	if (nframes == 0) return;
- 	
--	fractional_shift = -1.0/declick;
-+	fractional_shift = -1.0/(declick-1);
- 
- 	if (target < initial) {
- 		/* fade out: remove more and more of delta from initial */
-@@ -2683,7 +2683,7 @@ IO::end_gain_touch ()
-                 when = _session.transport_frame();
-         }
- 
--	_gain_automation_curve.stop_touch (mark, when);
-+	_gain_automation_curve.stop_touch (mark, when, gain());
- }
- 
- void
-@@ -2706,7 +2706,7 @@ IO::end_pan_touch (uint32_t which)
-                         when = _session.transport_frame();
-                 }
-                 
--		(*_panner)[which]->automation().stop_touch(mark, when);
-+		(*_panner)[which]->automation().stop_touch(mark, when, 0);
- 	}
- }
- 
-diff --git a/libs/ardour/po/el.po b/libs/ardour/po/el.po
-index 9ddd3e7..e0b74b3 100644
---- a/libs/ardour/po/el.po
-+++ b/libs/ardour/po/el.po
-@@ -5,7 +5,7 @@
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: libardour 0.664.0\n"
-+"Project-Id-Version: libardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2003-06-29 21:03+0200\n"
- "PO-Revision-Date: 2007-04-16 00:38+0200\n"
-diff --git a/libs/ardour/po/es.po b/libs/ardour/po/es.po
-index 0cdee7a..695a388 100644
---- a/libs/ardour/po/es.po
-+++ b/libs/ardour/po/es.po
-@@ -5,7 +5,7 @@
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: Ardour\n"
-+"Project-Id-Version: libardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2010-01-17 23:34+0100\n"
- "PO-Revision-Date: \n"
-diff --git a/libs/ardour/po/fr.po b/libs/ardour/po/fr.po
-index d1d6024..11a8498 100644
---- a/libs/ardour/po/fr.po
-+++ b/libs/ardour/po/fr.po
-@@ -5,7 +5,7 @@
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: PACKAGE VERSION\n"
-+"Project-Id-Version: libardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2010-04-27 16:38+0200\n"
- "PO-Revision-Date: 2010-04-27 16:39+0100\n"
-diff --git a/libs/ardour/po/it.po b/libs/ardour/po/it.po
-index 2ce0282..845bbeb 100644
---- a/libs/ardour/po/it.po
-+++ b/libs/ardour/po/it.po
-@@ -5,7 +5,7 @@
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: libardour 0.664.0\n"
-+"Project-Id-Version: libardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2006-06-29 21:03-0400\n"
- "PO-Revision-Date: 2003-05-21 12:50+0500\n"
-diff --git a/libs/ardour/po/nn.po b/libs/ardour/po/nn.po
-index eb15531..f79e125 100644
---- a/libs/ardour/po/nn.po
-+++ b/libs/ardour/po/nn.po
-@@ -6,7 +6,7 @@
- # Eivind Ødegård <gingermig at yahoo.no>, 2009.
- msgid ""
- msgstr ""
--"Project-Id-Version: nn_NO\n"
-+"Project-Id-Version: libardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2009-12-24 15:13+0100\n"
- "PO-Revision-Date: 2010-01-09 23:28+0100\n"
-diff --git a/libs/ardour/po/pl.po b/libs/ardour/po/pl.po
-index 3a39989..590b95a 100644
---- a/libs/ardour/po/pl.po
-+++ b/libs/ardour/po/pl.po
-@@ -5,7 +5,7 @@
- # Piotr Zaryk <pzaryk at gmail.com>, 2008.
- msgid ""
- msgstr ""
--"Project-Id-Version: libardour2\n"
-+"Project-Id-Version: libardour\n"
- "Report-Msgid-Bugs-To: Piotr Zaryk <pzaryk at gmail.com>\n"
- "POT-Creation-Date: 2008-04-03 16:16+0200\n"
- "PO-Revision-Date: 2008-04-10 10:51+0100\n"
-diff --git a/libs/ardour/po/ru.po b/libs/ardour/po/ru.po
-index 6e6d754..0e62956 100644
---- a/libs/ardour/po/ru.po
-+++ b/libs/ardour/po/ru.po
-@@ -6,7 +6,7 @@
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: libardour 0.716.1\n"
-+"Project-Id-Version: libardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2009-10-05 17:23+0400\n"
- "PO-Revision-Date: 2009-10-06 02:59+0300\n"
-diff --git a/libs/ardour/po/sv.po b/libs/ardour/po/sv.po
-index 8d4d423..4907025 100644
---- a/libs/ardour/po/sv.po
-+++ b/libs/ardour/po/sv.po
-@@ -5,7 +5,7 @@
- #
- msgid ""
- msgstr ""
--"Project-Id-Version: ardour\n"
-+"Project-Id-Version: libardour\n"
- "Report-Msgid-Bugs-To: \n"
- "POT-Creation-Date: 2006-10-03 00:39+0200\n"
- "PO-Revision-Date: 2006-10-03 01:09+GMT+1\n"
-diff --git a/libs/ardour/port.cc b/libs/ardour/port.cc
-index f218cbc..00603c9 100644
---- a/libs/ardour/port.cc
-+++ b/libs/ardour/port.cc
-@@ -63,4 +63,14 @@ Port::set_name (string str)
- 	return ret;
- }
- 
--	
-+nframes_t
-+Port::latency () const
-+{
-+	return jack_port_get_latency (_port);
-+}
-+
-+void 
-+Port::set_latency (nframes_t nframes)
-+{
-+	jack_port_set_latency (_port, nframes);
-+}
-diff --git a/libs/ardour/route_group.cc b/libs/ardour/route_group.cc
-index fbf118e..30cd35f 100644
---- a/libs/ardour/route_group.cc
-+++ b/libs/ardour/route_group.cc
-@@ -17,7 +17,6 @@
- 
- */
- 
--#define __STDC_FORMAT_MACROS
- #include <inttypes.h>
- 
- #include <algorithm>
-diff --git a/libs/ardour/session.cc b/libs/ardour/session.cc
-index 543f5f9..49d3858 100644
---- a/libs/ardour/session.cc
-+++ b/libs/ardour/session.cc
-@@ -2631,7 +2631,7 @@ Session::find_current_end ()
- 
- 	nframes_t max = get_maximum_extent ();
- 
--	if (max > end_location->end()) {
-+	if ( (max > end_location->end() ) && _end_location_is_free ) {
- 		end_location->set_end (max);
- 		set_dirty();
- 		DurationChanged(); /* EMIT SIGNAL */
-diff --git a/libs/ardour/session_state.cc b/libs/ardour/session_state.cc
-index 6e63094..e3e54f8 100644
---- a/libs/ardour/session_state.cc
-+++ b/libs/ardour/session_state.cc
-@@ -2272,6 +2272,7 @@ RouteGroup *
- Session::add_edit_group (string name)
- {
- 	RouteGroup* rg = new RouteGroup (*this, name);
-+	rg->set_active(true, this);
- 	edit_groups.push_back (rg);
- 	edit_group_added (rg); /* EMIT SIGNAL */
- 	set_dirty();
-@@ -2282,6 +2283,7 @@ RouteGroup *
- Session::add_mix_group (string name)
- {
- 	RouteGroup* rg = new RouteGroup (*this, name, RouteGroup::Relative);
-+	rg->set_active(true, this);
- 	mix_groups.push_back (rg);
- 	mix_group_added (rg); /* EMIT SIGNAL */
- 	set_dirty();
-diff --git a/libs/ardour/session_transport.cc b/libs/ardour/session_transport.cc
-index f26be79..88c6de1 100644
---- a/libs/ardour/session_transport.cc
-+++ b/libs/ardour/session_transport.cc
-@@ -941,7 +941,6 @@ Session::set_transport_speed (float speed, bool abort, bool clear_state)
- 		for (DiskstreamList::iterator i = dsl->begin(); i != dsl->end(); ++i) {
- 			if ((*i)->realtime_set_speed ((*i)->speed(), true)) {
- 				todo = PostTransportWork (todo | PostTransportSpeed);
--				break;
- 			}
- 		}
- 		
-diff --git a/libs/ardour/sndfilesource.cc b/libs/ardour/sndfilesource.cc
-index 1759b4a..2fa16d9 100644
---- a/libs/ardour/sndfilesource.cc
-+++ b/libs/ardour/sndfilesource.cc
-@@ -633,7 +633,7 @@ bool
- SndFileSource::set_destructive (bool yn)
- {
- 	if (yn) {
--		_flags = Flag (_flags | Destructive);
-+		_flags = Flag (_flags | Writable | Destructive);
- 		if (!xfade_buf) {
- 			xfade_buf = new Sample[xfade_frames];
- 		}
-@@ -644,7 +644,7 @@ SndFileSource::set_destructive (bool yn)
- 		timeline_position = 0;
- 		/* leave xfade buf alone in case we need it again later */
- 	}
--
-+        
- 	return true;
- }
- 
-diff --git a/libs/ardour/tempo.cc b/libs/ardour/tempo.cc
-index 6c91442..12e3e11 100644
---- a/libs/ardour/tempo.cc
-+++ b/libs/ardour/tempo.cc
-@@ -299,7 +299,21 @@ TempoMap::move_metric_section (MetricSection& section, const BBT_Time& when)
- void
- TempoMap::move_tempo (TempoSection& tempo, const BBT_Time& when)
- {
--	if (move_metric_section (tempo, when) == 0) {
-+	/* a new tempo always starts a new bar on the first beat */
-+	BBT_Time when_rounded = when;
-+	int force_state_changed = 0;
-+
-+	if (when_rounded.beats != 1) {
-+		when_rounded.beats = 1;
-+		when_rounded.bars++;
-+		force_state_changed = 1;
-+	}
-+
-+	/* new tempo *always* start on a beat. */
-+		
-+	when_rounded.ticks = 0;
-+
-+	if ((move_metric_section (tempo, when_rounded) == 0) || force_state_changed) {
- 		StateChanged (Change (0));
- 	}
- }
-@@ -307,7 +321,21 @@ TempoMap::move_tempo (TempoSection& tempo, const BBT_Time& when)
- void
- TempoMap::move_meter (MeterSection& meter, const BBT_Time& when)
- {
--	if (move_metric_section (meter, when) == 0) {
-+	/* a new meter always starts a new bar on the first beat */
-+	BBT_Time when_rounded = when;
-+	int force_state_changed = 0;
-+
-+	if (when_rounded.beats != 1) {
-+		when_rounded.beats = 1;
-+		when_rounded.bars++;
-+		force_state_changed = 1;
-+	}
-+
-+	/* new meters *always* start on a beat. */
-+		
-+	when_rounded.ticks = 0;
-+
-+	if ((move_metric_section (meter, when_rounded) == 0) || force_state_changed) {
- 		StateChanged (Change (0));
- 	}
- }
-diff --git a/libs/gtkmm2ext/barcontroller.cc b/libs/gtkmm2ext/barcontroller.cc
-index 7ce1fc7..31bf102 100644
---- a/libs/gtkmm2ext/barcontroller.cc
-+++ b/libs/gtkmm2ext/barcontroller.cc
-@@ -146,7 +146,6 @@ BarController::entry_output ()
- 	
- 	stringstream stream;
- 	string str;
--	size_t found;
- 
- 	char buf[128];
- 
-diff --git a/libs/gtkmm2ext/gtk_ui.cc b/libs/gtkmm2ext/gtk_ui.cc
-index 25501a2..291740c 100644
---- a/libs/gtkmm2ext/gtk_ui.cc
-+++ b/libs/gtkmm2ext/gtk_ui.cc
-@@ -52,6 +52,7 @@ using std::map;
- pthread_t UI::gui_thread;
- UI       *UI::theGtkUI = 0;
- 
-+BaseUI::RequestType Gtkmm2ext::NullRequest = BaseUI::new_request_type();
- BaseUI::RequestType Gtkmm2ext::ErrorMessage = BaseUI::new_request_type();
- BaseUI::RequestType Gtkmm2ext::Quit = BaseUI::new_request_type();
- BaseUI::RequestType Gtkmm2ext::TouchDisplay = BaseUI::new_request_type();
-diff --git a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
-index 4d4d718..c3352f6 100644
---- a/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
-+++ b/libs/gtkmm2ext/gtkmm2ext/gtk_ui.h
-@@ -51,6 +51,7 @@ namespace Gtkmm2ext {
- 
- class TextViewer;
- 
-+extern BaseUI::RequestType NullRequest;
- extern BaseUI::RequestType ErrorMessage;
- extern BaseUI::RequestType Quit;
- extern BaseUI::RequestType CallSlot;
-@@ -77,6 +78,10 @@ struct UIRequest : public BaseUI::BaseRequestObject {
-     void *arg;
-     const char *msg2;
-     sigc::slot<void> slot;
-+
-+    UIRequest () {
-+            type = NullRequest;
-+    }
-     
-     ~UIRequest () { 
- 	    if (type == ErrorMessage && msg) {
-diff --git a/libs/pbd/SConscript b/libs/pbd/SConscript
-index b33ab58..1c2ee94 100644
---- a/libs/pbd/SConscript
-+++ b/libs/pbd/SConscript
-@@ -26,6 +26,7 @@ copyfile.cc
- controllable.cc
- enumwriter.cc
- dmalloc.cc
-+epa.cc
- error.cc
- fpu.cc
- id.cc
-diff --git a/libs/pbd/convert.cc b/libs/pbd/convert.cc
-index 218ac6b..598473c 100644
---- a/libs/pbd/convert.cc
-+++ b/libs/pbd/convert.cc
-@@ -23,9 +23,6 @@
- #include <locale>
- #include <algorithm>
- #include <stdint.h>
--#ifndef __STDC_FORMAT_MACROS
--#define __STDC_FORMAT_MACROS
--#endif
- #include <inttypes.h>
- 
- #include "pbd/convert.h"
-diff --git a/libs/pbd/enumwriter.cc b/libs/pbd/enumwriter.cc
-index 7033e5f..e7576f2 100644
---- a/libs/pbd/enumwriter.cc
-+++ b/libs/pbd/enumwriter.cc
-@@ -174,6 +174,98 @@ EnumWriter::write_distinct (EnumRegistration& er, int value)
- 	return string();
- }
- 
-+string
-+EnumWriter::validate_string (EnumRegistration& er, const string& str)
-+{
-+        int val;
-+
-+        if (er.values.empty()) {
-+                return str;
-+        }
-+
-+        if (er.bitwise) {
-+                /* Legal values consist of OR-ed masks of zero or more values defined an enum.
-+                   Since we only ever check the legal bits, any value is acceptable,
-+                   including zero.
-+                */
-+                return str;
-+        } 
-+
-+        val = atoi (str.c_str());
-+
-+        /* not bitwise: Legal values consist of discrete values defined by an enum */
-+
-+        for (vector<int>::iterator i = er.values.begin(); i != er.values.end(); ++i) {
-+                if (*i == val) {
-+                        return str; /* string is a legal representation of a enumerated single value */
-+                }
-+        } 
-+        
-+        string enum_name = _("unknown enumeration");
-+        
-+        for (Registry::iterator x = registry.begin(); x != registry.end(); ++x) {
-+                if (&er == &(*x).second) {
-+                        enum_name = (*x).first;
-+                }
-+        }
-+
-+        warning << string_compose (_("Illegal value loaded for %1 (%2) - %3 used instead"),
-+                                   enum_name, val, er.names.front()) 
-+                << endmsg;
-+
-+        stringstream ss;
-+        ss << er.values.front();
-+
-+        return ss.str();
-+}
-+
-+string
-+EnumWriter::typed_validate (const string& type, const string& value_str) 
-+{
-+        for (Registry::iterator x = registry.begin(); x != registry.end(); ++x) {
-+                if (x->first == type) {
-+                        return validate_string (x->second, value_str);
-+                }
-+        }        
-+
-+        /* not a known enum */
-+
-+        return value_str;
-+}
-+
-+int
-+EnumWriter::validate (EnumRegistration& er, int val)
-+{
-+        if (er.values.empty()) {
-+                return val;
-+        }
-+
-+        if (er.bitwise) {
-+                return val;
-+        }
-+
-+        vector<int>::iterator i;
-+        string enum_name = _("unknown enumeration");
-+        
-+        for (Registry::iterator x = registry.begin(); x != registry.end(); ++x) {
-+                if (&er == &(*x).second) {
-+                        enum_name = (*x).first;
-+                }
-+        }
-+        
-+
-+        for (i = er.values.begin(); i != er.values.end(); ++i) {
-+                if (*i == val) {
-+                        return val;
-+                }
-+        }
-+        
-+        warning << string_compose (_("Illegal value loaded for %1 (%2) - %3 used instead"),
-+                                   enum_name, val, er.names.front()) 
-+                << endmsg;
-+        return er.values.front();
-+}
-+
- int
- EnumWriter::read_bits (EnumRegistration& er, string str)
- {
-@@ -186,14 +278,16 @@ EnumWriter::read_bits (EnumRegistration& er, string str)
- 	/* catch old-style hex numerics */
- 
- 	if (str.length() > 2 && str[0] == '0' && str[1] == 'x') {
--		return strtol (str.c_str(), (char **) 0, 16);
-+		int val = strtol (str.c_str(), (char **) 0, 16);
-+                return validate (er, val);
- 	}
- 
- 	/* catch old style dec numerics */
- 
- 	if (strspn (str.c_str(), "0123456789") == str.length()) {
--		return strtol (str.c_str(), (char **) 0, 10);
--	}
-+		int val = strtol (str.c_str(), (char **) 0, 10);
-+                return validate (er, val);
-+        }
- 
- 	do {
- 		
-@@ -231,14 +325,16 @@ EnumWriter::read_distinct (EnumRegistration& er, string str)
- 	/* catch old-style hex numerics */
- 
- 	if (str.length() > 2 && str[0] == '0' && str[1] == 'x') {
--		return strtol (str.c_str(), (char **) 0, 16);
-+		int val = strtol (str.c_str(), (char **) 0, 16);
-+                return validate (er, val);
- 	}
- 
- 	/* catch old style dec numerics */
- 
- 	if (strspn (str.c_str(), "0123456789") == str.length()) {
--		return strtol (str.c_str(), (char **) 0, 10);
--	}
-+		int val = strtol (str.c_str(), (char **) 0, 10);
-+                return validate (er, val);
-+        }
- 
- 	for (i = er.values.begin(), s = er.names.begin(); i != er.values.end(); ++i, ++s) {
- 		if (str == (*s) || nocase_cmp (str, *s) == 0) {
-diff --git a/libs/pbd/epa.cc b/libs/pbd/epa.cc
-new file mode 100644
-index 0000000..3b6066d
---- /dev/null
-+++ b/libs/pbd/epa.cc
-@@ -0,0 +1,130 @@
-+/*
-+    Copyright (C) 2010 Paul Davis 
-+
-+    This program is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU General Public License as published by
-+    the Free Software Foundation; either version 2 of the License, or
-+    (at your option) any later version.
-+
-+    This program is distributed in the hope that it will be useful,
-+    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+    GNU General Public License for more details.
-+
-+    You should have received a copy of the GNU General Public License
-+    along with this program; if not, write to the Free Software
-+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+
-+*/
-+
-+#include <cstdlib>
-+#include <iostream>
-+
-+#include "pbd/epa.h"
-+#include "pbd/strsplit.h"
-+
-+#ifdef __APPLE__
-+#include <crt_externs.h>
-+#define environ (*_NSGetEnviron())
-+#else
-+extern char** environ;
-+#endif
-+
-+using namespace PBD;
-+using namespace std;
-+
-+EnvironmentalProtectionAgency* EnvironmentalProtectionAgency::_global_epa = 0;
-+
-+EnvironmentalProtectionAgency::EnvironmentalProtectionAgency (bool arm, const std::string& envname)
-+        : _armed (arm)
-+        , _envname (envname)
-+{
-+        if (_armed) {
-+                save ();
-+        }
-+}
-+
-+EnvironmentalProtectionAgency::~EnvironmentalProtectionAgency()
-+{
-+        if (_armed) {
-+                restore ();
-+        }
-+}
-+
-+void
-+EnvironmentalProtectionAgency::arm ()
-+{
-+        _armed = true;
-+}
-+
-+void
-+EnvironmentalProtectionAgency::save ()
-+{
-+	/* do this to avoid lots of calls to _NSGetEnviron() on OS X */
-+
-+	char** the_environ = environ;
-+
-+        e.clear ();
-+
-+        if (!_envname.empty()) {
-+                
-+                /* fetch environment from named environment variable, rather than "environ"
-+                 */
-+
-+                const char* estr = getenv (_envname.c_str());
-+
-+                if (!estr) {
-+                        return;
-+                }
-+                
-+                /* parse line by line, and save into "e" 
-+                 */
-+
-+                vector<string> lines;
-+                split (estr, lines, '\n');
-+
-+                for (vector<string>::iterator i = lines.begin(); i != lines.end(); ++i) {
-+
-+                        string estring = *i;
-+                        string::size_type equal = estring.find_first_of ('=');
-+                        
-+                        if (equal == string::npos) {
-+                                /* say what? an environ value without = ? */
-+                                continue;
-+                        }
-+                        
-+                        string before = estring.substr (0, equal);
-+                        string after = estring.substr (equal+1);
-+                        
-+                        e.insert (pair<string,string>(before,after));
-+                }
-+                
-+        } else {
-+
-+                /* fetch environment from "environ"
-+                 */
-+
-+                for (size_t i = 0; the_environ[i]; ++i) {
-+                        
-+                        string estring = the_environ[i];
-+                        string::size_type equal = estring.find_first_of ('=');
-+                        
-+                        if (equal == string::npos) {
-+                                /* say what? an environ value without = ? */
-+                                continue;
-+                        }
-+                        
-+                        string before = estring.substr (0, equal);
-+                        string after = estring.substr (equal+1);
-+                        
-+                        e.insert (pair<string,string>(before,after));
-+                }
-+        }
-+}                         
-+void
-+EnvironmentalProtectionAgency::restore () const
-+{
-+        for (map<string,string>::const_iterator i = e.begin(); i != e.end(); ++i) {
-+                setenv (i->first.c_str(), i->second.c_str(), 1);
-+        }
-+}                         
-diff --git a/libs/pbd/id.cc b/libs/pbd/id.cc
-index 642243a..acd50fc 100644
---- a/libs/pbd/id.cc
-+++ b/libs/pbd/id.cc
-@@ -21,9 +21,6 @@
- #include <iostream>
- #include <stdio.h>
- 
--#ifndef __STDC_FORMAT_MACROS
--#define __STDC_FORMAT_MACROS
--#endif
- #include <inttypes.h>
- 
- #include <pbd/id.h>
-diff --git a/libs/pbd/pbd/abstract_ui.cc b/libs/pbd/pbd/abstract_ui.cc
-index bc33fc9..24760fb 100644
---- a/libs/pbd/pbd/abstract_ui.cc
-+++ b/libs/pbd/pbd/abstract_ui.cc
-@@ -1,4 +1,5 @@
- #include <unistd.h>
-+#include <cstdlib>
- 
- #include <pbd/abstract_ui.h>
- #include <pbd/pthread_utils.h>
-@@ -8,11 +9,22 @@
- 
- using namespace std;
- 
-+template<typename RequestBuffer> void 
-+cleanup_request_buffer (void* ptr)
-+{
-+        RequestBuffer* rb = (RequestBuffer*) ptr;
-+
-+        {
-+                Glib::Mutex::Lock lm (rb->ui.request_buffer_map_lock);
-+                rb->dead = true;
-+        }
-+}
-+
- template <typename RequestObject>
- AbstractUI<RequestObject>::AbstractUI (string name, bool with_signal_pipes)
- 	: BaseUI (name, with_signal_pipes)
- {
--	if (pthread_key_create (&thread_request_buffer_key, 0)) {
-+	if (pthread_key_create (&thread_request_buffer_key, cleanup_request_buffer<RequestBuffer>)) {
- 		cerr << _("cannot create thread request buffer key") << endl;
- 		throw failed_constructor();
- 	}
-@@ -30,10 +42,24 @@ AbstractUI<RequestObject>::register_thread (pthread_t thread_id, string name)
- template <typename RequestObject> void
- AbstractUI<RequestObject>::register_thread_with_request_count (pthread_t thread_id, string thread_name, uint32_t num_requests)
- {
--	RequestBuffer* b = new RequestBuffer (num_requests);
-+	RequestBuffer* rbuf = static_cast<RequestBuffer*>(pthread_getspecific (thread_request_buffer_key));
-+
-+        /* we require that the thread being registered is the caller */
-+
-+        if (thread_id != pthread_self()) {
-+                cerr << "thread attempts to register some other thread with the UI named " << name() << endl;
-+                abort ();
-+        }
- 
-+        if (rbuf) {
-+                /* this thread is already registered with this AbstractUI */
-+                return;
-+        }
-+
-+	RequestBuffer* b = new RequestBuffer (num_requests, *this);
-+        
- 	{
--        Glib::Mutex::Lock lm (request_buffer_map_lock);
-+                Glib::Mutex::Lock lm (request_buffer_map_lock);
- 		request_buffers[thread_id] = b;
- 	}
- 
-@@ -93,33 +119,42 @@ AbstractUI<RequestObject>::handle_ui_requests ()
- 
- 	request_buffer_map_lock.lock ();
- 
--	for (i = request_buffers.begin(); i != request_buffers.end(); ++i) {
-+	for (i = request_buffers.begin(); i != request_buffers.end(); ) {
- 
- 		RequestBufferVector vec;
- 
--		while (true) {
--
--			/* we must process requests 1 by 1 because
--			   the request may run a recursive main
--			   event loop that will itself call
--			   handle_ui_requests. when we return
--			   from the request handler, we cannot
--			   expect that the state of queued requests
--			   is even remotely consistent with
--			   the condition before we called it.
--			*/
--
--			i->second->get_read_vector (&vec);
--
--			if (vec.len[0] == 0) {
--				break;
--			} else {
--				request_buffer_map_lock.unlock ();
--				do_request (vec.buf[0]);
--				request_buffer_map_lock.lock ();
--				i->second->increment_read_ptr (1);
--			} 
--		}
-+                if ((*i).second->dead) {
-+                        delete (*i).second;
-+                        RequestBufferMapIterator tmp = i;
-+                        ++tmp;
-+                        request_buffers.erase (i);
-+                        i = tmp;
-+                } else {
-+                        while (true) {
-+                                
-+                                /* we must process requests 1 by 1 because
-+                                   the request may run a recursive main
-+                                   event loop that will itself call
-+                                   handle_ui_requests. when we return
-+                                   from the request handler, we cannot
-+                                   expect that the state of queued requests
-+                                   is even remotely consistent with
-+                                   the condition before we called it.
-+                                */
-+                                
-+                                i->second->get_read_vector (&vec);
-+                                
-+                                if (vec.len[0] == 0) {
-+                                        break;
-+                                } else {
-+                                        request_buffer_map_lock.unlock ();
-+                                        do_request (vec.buf[0]);
-+                                        request_buffer_map_lock.lock ();
-+                                        i->second->increment_read_ptr (1);
-+                                } 
-+                        }
-+                        ++i;
-+                }
- 	}
- 
- 	request_buffer_map_lock.unlock ();
-diff --git a/libs/pbd/pbd/abstract_ui.h b/libs/pbd/pbd/abstract_ui.h
-index 7718d94..f20d0a3 100644
---- a/libs/pbd/pbd/abstract_ui.h
-+++ b/libs/pbd/pbd/abstract_ui.h
-@@ -58,12 +58,21 @@ class AbstractUI : public BaseUI
- 	void register_thread_with_request_count (pthread_t, std::string, uint32_t num_requests);
- 	void unregister_thread (pthread_t);
- 
-+        Glib::Mutex request_buffer_map_lock;
-+
-   protected:
--	typedef RingBufferNPT<RequestObject> RequestBuffer;
-+        struct RequestBuffer : public RingBufferNPT<RequestObject> {
-+                bool dead;
-+                AbstractUI<RequestObject>& ui;
-+                RequestBuffer (uint32_t size, AbstractUI<RequestObject>& uir) 
-+                        : RingBufferNPT<RequestObject> (size)
-+                        , dead (false) 
-+                        , ui (uir) {}
-+        };
-+
- 	typedef typename RequestBuffer::rw_vector RequestBufferVector;
- 	typedef typename std::map<pthread_t,RequestBuffer*>::iterator RequestBufferMapIterator;
- 
--    Glib::Mutex request_buffer_map_lock;
- 	typedef std::map<pthread_t,RequestBuffer*> RequestBufferMap;
- 	RequestBufferMap request_buffers;
- 	pthread_key_t thread_request_buffer_key;
-diff --git a/libs/pbd/pbd/enumwriter.h b/libs/pbd/pbd/enumwriter.h
-index f53388f..abc803c 100644
---- a/libs/pbd/pbd/enumwriter.h
-+++ b/libs/pbd/pbd/enumwriter.h
-@@ -18,6 +18,9 @@
-     $Id$
- */
- 
-+#ifndef __pbd_enumwriter_h__
-+#define __pbd_enumwriter_h__
-+
- #include <map>
- #include <string>
- #include <vector>
-@@ -45,6 +48,7 @@ class EnumWriter {
- 	int         read  (std::string type, std::string value);
- 
- 	void add_to_hack_table (std::string str, std::string hacked_str);
-+        std::string typed_validate (const std::string& type, const std::string&);
- 
-   private:
- 	struct EnumRegistration {
-@@ -68,10 +72,16 @@ class EnumWriter {
- 
- 	static EnumWriter* _instance;
- 	static std::map<std::string,std::string> hack_table;
-+
-+        int validate (EnumRegistration& er, int value);
-+
-+        std::string validate_string (EnumRegistration& er, const std::string&);
- };
- 
- }
- 
-+#define enum_validate(v,str) PBD::EnumWriter::instance().typed_validate (typeid(v).name(),str)
- #define enum_2_string(e) (PBD::EnumWriter::instance().write (typeid(e).name(), e))
- #define string_2_enum(str,e) (PBD::EnumWriter::instance().read (typeid(e).name(), (str)))
- 
-+#endif /* __pbd_enumwriter_h__ */
-diff --git a/libs/pbd/pbd/epa.h b/libs/pbd/pbd/epa.h
-new file mode 100644
-index 0000000..ffcd785
---- /dev/null
-+++ b/libs/pbd/pbd/epa.h
-@@ -0,0 +1,49 @@
-+/*
-+    Copyright (C) 2010 Paul Davis 
-+
-+    This program is free software; you can redistribute it and/or modify
-+    it under the terms of the GNU General Public License as published by
-+    the Free Software Foundation; either version 2 of the License, or
-+    (at your option) any later version.
-+
-+    This program is distributed in the hope that it will be useful,
-+    but WITHOUT ANY WARRANTY; without even the implied warranty of
-+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+    GNU General Public License for more details.
-+
-+    You should have received a copy of the GNU General Public License
-+    along with this program; if not, write to the Free Software
-+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+
-+*/
-+
-+#ifndef __libpbd_epa_h__
-+#define __libpbd_epa_h__
-+
-+#include <map>
-+#include <string>
-+
-+namespace PBD {
-+
-+class EnvironmentalProtectionAgency {
-+  public:
-+        EnvironmentalProtectionAgency (bool arm = true, const std::string& envname = std::string());
-+        ~EnvironmentalProtectionAgency ();
-+        
-+        void arm ();
-+        void save ();
-+        void restore () const;
-+        
-+        static EnvironmentalProtectionAgency* get_global_epa () { return _global_epa; }
-+        static void set_global_epa (EnvironmentalProtectionAgency* epa) { _global_epa = epa; }
-+        
-+  private:
-+        bool _armed;
-+        std::string _envname;
-+        std::map<std::string,std::string> e;
-+        static EnvironmentalProtectionAgency* _global_epa;
-+};
-+
-+}
-+
-+#endif /* __libpbd_epa_h__ */
-diff --git a/libs/pbd/undo.cc b/libs/pbd/undo.cc
-index 2e2686d..28a1cc4 100644
---- a/libs/pbd/undo.cc
-+++ b/libs/pbd/undo.cc
-@@ -40,6 +40,8 @@ UndoTransaction::UndoTransaction (const UndoTransaction& rhs)
- {
- 	_name = rhs._name;
- 	_clearing = false;
-+        _timestamp = rhs._timestamp;
-+
- 	clear ();
- 	actions.insert(actions.end(),rhs.actions.begin(),rhs.actions.end());
- }
-diff --git a/libs/rubberband/rubberband/RubberBandStretcher.h b/libs/rubberband/rubberband/RubberBandStretcher.h
-index 1e676f2..48343c7 100644
---- a/libs/rubberband/rubberband/RubberBandStretcher.h
-+++ b/libs/rubberband/rubberband/RubberBandStretcher.h
-@@ -19,6 +19,7 @@
- #define RUBBERBAND_API_MAJOR_VERSION 2
- #define RUBBERBAND_API_MINOR_VERSION 0
- 
-+#include <cstddef>
- #include <vector>
- 
- /**
-diff --git a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
-index d5ad64d..3b784f4 100644
---- a/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
-+++ b/libs/surfaces/generic_midi/generic_midi_control_protocol.cc
-@@ -17,7 +17,6 @@
- 
- */
- 
--#define __STDC_FORMAT_MACROS 1
- #include <stdint.h>
- 
- #include <algorithm>
-diff --git a/libs/surfaces/mackie/mackie_control_protocol.cc b/libs/surfaces/mackie/mackie_control_protocol.cc
-index 5ba1d64..7cb017f 100644
---- a/libs/surfaces/mackie/mackie_control_protocol.cc
-+++ b/libs/surfaces/mackie/mackie_control_protocol.cc
-@@ -23,7 +23,6 @@
- #include <vector>
- #include <iomanip>
- 
--#define __STDC_FORMAT_MACROS
- #include <inttypes.h>
- #include <float.h>
- #include <sys/time.h>
-@@ -622,9 +621,15 @@ MackieControlProtocol::add_port( MIDI::Port & midi_port, int number )
- 	cout << "MIDI::Port::ALSA_Sequencer " << MIDI::Port::ALSA_Sequencer << endl;
- 	cout << "MIDI::Port::Unknown " << MIDI::Port::Unknown << endl;
- #endif
--	if ( string( midi_port.device() ) == string( "ardour" ) && midi_port.type() == MIDI::Port::ALSA_Sequencer )
-+        string pname (PROGRAM_NAME);
-+        std::transform(pname.begin(), pname.end(), pname.begin(), ::tolower);
-+
-+	if ( string( midi_port.device() ) == pname && midi_port.type() == MIDI::Port::ALSA_Sequencer )
- 	{
--		throw MackieControlException( "The Mackie MCU driver will not use a port with device=ardour" );
-+                ostringstream s;
-+                s << "The Mackie MCU driver will not use a port with device=";
-+                s << pname;
-+		throw MackieControlException( s.str());
- 	}
- 	else if ( midi_port.type() == MIDI::Port::ALSA_Sequencer )
- 	{
-diff --git a/libs/surfaces/mackie/mackie_port.cc b/libs/surfaces/mackie/mackie_port.cc
-index d767c4c..35c681c 100644
---- a/libs/surfaces/mackie/mackie_port.cc
-+++ b/libs/surfaces/mackie/mackie_port.cc
-@@ -488,6 +488,12 @@ void MackiePort::handle_midi_any (MIDI::Parser & parser, MIDI::byte * raw_bytes,
- 				state.sign = ( raw_bytes[2] & 0x40 ) == 0 ? 1 : -1; 
- 				// bytes[2] & 0b00111111 (0x3f) gives delta
- 				state.ticks = ( raw_bytes[2] & 0x3f);
-+                                if (state.ticks == 0) {
-+                                        /* euphonix and perhaps other devices send zero
-+                                           when they mean 1, we think.
-+                                        */
-+                                        state.ticks = 1;
-+                                }
- 				state.delta = float( state.ticks ) / float( 0x3f );
- 				
- 				/*
-diff --git a/libs/surfaces/tranzport/io_usb.cc b/libs/surfaces/tranzport/io_usb.cc
-index c4a004a..6a63862 100644
---- a/libs/surfaces/tranzport/io_usb.cc
-+++ b/libs/surfaces/tranzport/io_usb.cc
-@@ -20,7 +20,6 @@
- 
- #include <iostream>
- 
--#define __STDC_FORMAT_MACROS
- #include <inttypes.h>
- #include <float.h>
- #include <sys/time.h>
-diff --git a/libs/surfaces/tranzport/show.cc b/libs/surfaces/tranzport/show.cc
-index 04e641e..0d6453f 100644
---- a/libs/surfaces/tranzport/show.cc
-+++ b/libs/surfaces/tranzport/show.cc
-@@ -22,7 +22,6 @@
- #include <algorithm>
- #include <cmath>
- 
--#define __STDC_FORMAT_MACROS
- #include <inttypes.h>
- #include <float.h>
- #include <sys/time.h>
-diff --git a/libs/surfaces/tranzport/state.cc b/libs/surfaces/tranzport/state.cc
-index 1cb55b4..cb566be 100644
---- a/libs/surfaces/tranzport/state.cc
-+++ b/libs/surfaces/tranzport/state.cc
-@@ -22,7 +22,6 @@
- #include <algorithm>
- #include <cmath>
- 
--#define __STDC_FORMAT_MACROS
- #include <inttypes.h>
- #include <float.h>
- #include <sys/time.h>
-diff --git a/libs/surfaces/tranzport/tranzport_common.h b/libs/surfaces/tranzport/tranzport_common.h
-index 06b07bd..34a3a90 100644
---- a/libs/surfaces/tranzport/tranzport_common.h
-+++ b/libs/surfaces/tranzport/tranzport_common.h
-@@ -26,7 +26,6 @@
- #include <algorithm>    
- #include <cmath>        
-   
--#define __STDC_FORMAT_MACROS
- #include <inttypes.h>
- #include <float.h>
- #include <sys/time.h>
-diff --git a/libs/surfaces/tranzport/wheel.cc b/libs/surfaces/tranzport/wheel.cc
-index bc9683e..3256f36 100644
---- a/libs/surfaces/tranzport/wheel.cc
-+++ b/libs/surfaces/tranzport/wheel.cc
-@@ -22,7 +22,6 @@
- #include <algorithm>
- #include <cmath>
- 
--#define __STDC_FORMAT_MACROS
- #include <inttypes.h>
- #include <float.h>
- #include <sys/time.h>
-diff --git a/libs/surfaces/tranzport/wheel_modes.cc b/libs/surfaces/tranzport/wheel_modes.cc
-index 06b3ae0..0bc7051 100644
---- a/libs/surfaces/tranzport/wheel_modes.cc
-+++ b/libs/surfaces/tranzport/wheel_modes.cc
-@@ -22,7 +22,6 @@
- #include <algorithm>
- #include <cmath>
- 
--#define __STDC_FORMAT_MACROS
- #include <inttypes.h>
- #include <float.h>
- #include <sys/time.h>
-diff --git a/libs/surfaces/wiimote/wiimote.cc b/libs/surfaces/wiimote/wiimote.cc
-index af3bbc3..f4a8047 100644
---- a/libs/surfaces/wiimote/wiimote.cc
-+++ b/libs/surfaces/wiimote/wiimote.cc
-@@ -177,7 +177,7 @@ wiimote_discovery:
- 	std::cerr << "Wiimote: discovering, press 1+2" << std::endl;
- 
-  	while (!wiimote_handle && !main_thread_quit) {
--		bdaddr = *BDADDR_ANY;
-+		bdaddr = (bdaddr_t) {{0, 0, 0, 0, 0, 0}};
- 		callback_thread_registered_for_ardour = false;
- 		wiimote_handle = cwiid_open(&bdaddr, 0);
- 
-diff --git a/libs/vamp-plugins/SConscript b/libs/vamp-plugins/SConscript
-index fd86c09..20cdb33 100644
---- a/libs/vamp-plugins/SConscript
-+++ b/libs/vamp-plugins/SConscript
-@@ -10,9 +10,6 @@ AmplitudeFollower.cpp
- PercussionOnsetDetector.cpp
- SpectralCentroid.cpp
- ZeroCrossing.cpp
--""")
--
--aubio_files = Split ("""
- Onset.cpp
- """)
- 
-@@ -21,18 +18,13 @@ vampplugs = env.Clone()
- 
- vampplugs.Append (CPPATH='#libs/vamp-sdk/vamp', CXXFLAGS="-Ilibs/vamp-sdk")
- vampplugs.Merge ([libraries['vamp'],
--                  libraries['vamphost']
-+                  libraries['vamphost'],
-+                  libraries['aubio'],
-+                  libraries['fftw3f']
-                   ])
- 
- sources = plugin_files
- 
--if vampplugs['AUBIO']:
--    sources += aubio_files
--    vampplugs.Merge ([libraries['aubio']])
--    vampplugs.Merge ([libraries['fftw3f']])
--else:
--    print 'WARNING: some VAMP plugins will not be built because this machine has no AUBIO support'
--
- libvampplugins = vampplugs.SharedLibrary('ardourvampplugins', sources)
- 
- Default(libvampplugins)
-@@ -41,5 +33,5 @@ env.Alias('install', env.Install(os.path.join(install_prefix, env['LIBDIR'], 'ar
- 
- env.Alias('tarball', env.Distribute (env['DISTTREE'],
-                                      [ 'SConscript' ] +
--                                     plugin_files + aubio_files +
-+                                     plugin_files +
-                                      glob.glob('*.h')))
-diff --git a/tools/linux_packaging/README b/tools/linux_packaging/README
-new file mode 100644
-index 0000000..fb99aa8
---- /dev/null
-+++ b/tools/linux_packaging/README
-@@ -0,0 +1,35 @@
-+* Installing Ardour:
-+
-+On most distributions, you can double-click the file "install.sh".
-+
-+Alternatively, you can use a Terminal to run the installer.  Navigate
-+to the folder and run:
-+	
-+	./install.sh
-+	
-+The installer will ask for your root password, and copy the contents of
-+the appropriate bundle (32-bit or 64-bit) to your /opt folder.
-+
-+
-+* Links and Menu entries:
-+
-+In addition to installing the program, the installer will create:
-+1) A desktop link to launch the Ardour application
-+2) A menu entry in Gnome/KDE
-+3) An uninstall script in the /opt folder.
-+
-+
-+* Uninstaller:
-+
-+To uninstall Ardour, run the uninstaller script in the /opt folder
-+(as root).  This will remove the app, desktop links, menu links, and
-+the uninstaller itself.
-+
-+
-+* Manual Installation:
-+
-+If you would prefer to install Ardour in a custom location, then you
-+may simply unzip the appropriate package (32bit or 64bit) to your
-+preferred location and run the Ardour application from the "bin"
-+folder inside.
-+
-diff --git a/tools/linux_packaging/ardour.sh.in b/tools/linux_packaging/ardour.sh.in
-new file mode 100644
-index 0000000..52d5032
---- /dev/null
-+++ b/tools/linux_packaging/ardour.sh.in
-@@ -0,0 +1,56 @@
-+#!/bin/sh
-+
-+while [ $# -gt 0 ] ; do
-+	echo "arg = $1"
-+	case $1 in
-+
-+	-d)
-+		DEBUG="T";
-+		shift ;;
-+	*)      break;;
-+	esac
-+done
-+
-+#LD_LIBRARY_PATH needs to be set (empty) so that epa can swap between the original and the bundled version
-+export LD_LIBRARY_PATH=${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
-+
-+export PREBUNDLE_ENV="$(env)"
-+
-+BIN_DIR=$(dirname $(readlink -f $0))
-+INSTALL_DIR=$(dirname $BIN_DIR)
-+LIB_DIR=$INSTALL_DIR/lib
-+ETC_DIR=$INSTALL_DIR/etc
-+USER_ARDOUR_DIR=$HOME/.ardour2
-+
-+if [ ! -d $USER_ARDOUR_DIR ] ; then
-+    mkdir -p $USER_ARDOUR_DIR || exit 1
-+fi
-+
-+# this triggers code in main() that will reset runtime environment variables
-+# to point to directories inside the ardour package
-+
-+export ARDOUR_BUNDLED=true
-+
-+# this is edited by the build script to include relevant environment variables
-+
-+%ENV%
-+
-+export GTK_PATH=$INSTALL_DIR${GTK_PATH:+:$GTK_PATH}
-+export GTK_MODULES=""		# Disable extra modules from being loaded by gtk (example, libcanberra-gtk-module.so)
-+export LD_LIBRARY_PATH=$INSTALL_DIR/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
-+
-+# create install-location-dependent config files for Pango and GDK image loaders
-+# We have to do this every time because its possible that BIN_DIR has changed
-+
-+sed "s?@ROOTDIR@/modules?$LIB_DIR/modules?" < $ETC_DIR/pango.modules.in > $USER_ARDOUR_DIR/pango.modules
-+sed "s?@ROOTDIR@/loaders?$LIB_DIR/loaders?" < $ETC_DIR/gdk-pixbuf.loaders.in > $USER_ARDOUR_DIR/gdk-pixbuf.loaders
-+
-+if [ "T" = "$DEBUG" ]; then
-+	export ARDOUR_INSIDE_GDB=1
-+	exec gdb $INSTALL_DIR/bin/ardour-%VER% "$@"
-+else
-+	exec $INSTALL_DIR/bin/ardour-%VER% "$@"
-+fi
-+
-+
-+
-diff --git a/tools/linux_packaging/build b/tools/linux_packaging/build
-new file mode 100755
-index 0000000..5c8833c
---- /dev/null
-+++ b/tools/linux_packaging/build
-@@ -0,0 +1,660 @@
-+#!/bin/bash
-+
-+#
-+
-+. ./buildenv
-+
-+# script for pulling together a Linux app bundle.
-+#
-+# This will create a bundle for a single architecture.
-+# Execute this scirpt on both x86 and x86_64 and then use
-+# package to merge the 2 bundles into a final package with the
-+# installer.
-+
-+SAE=
-+MIXBUS=
-+INTERNAL_JACK=1
-+WITH_LADSPA=0
-+STRIP=all
-+PRINT_SYSDEPS=
-+WITH_NLS=
-+EXTERNAL_JACK=
-+VENDOR=Ardour ;
-+BUILDTYPE=""
-+
-+if [ $# -eq 0 ] ; then
-+	echo ""	 
-+	echo "ERROR - Please specify build type"
-+	echo "	  --public"
-+	echo "	  --sae"
-+	echo ""	 
-+	exit 1
-+fi
-+
-+while [ $# -gt 0 ] ; do
-+	echo "arg = $1"
-+	case $1 in
-+
-+	#
-+	# top level build targets
-+	#
-+
-+	--sae)
-+		WITH_NLS= ; 
-+		SAE=1 ; 
-+		INTERNAL_JACK=1; 
-+		WITH_LADSPA=1; 
-+		STRIP=all; 
-+		APPNAME=Ardour ;
-+		shift ;;
-+	--mixbus)
-+		MIXBUS=1; 
-+		WITH_NLS=1 ; 
-+		SAE= ; 
-+		INTERNAL_JACK=; 
-+		WITH_LADSPA=; 
-+		STRIP=all;
-+		APPNAME=Mixbus ;
-+		VENDOR=Harrison ;
-+		shift ;;
-+	--public)
-+		WITH_NLS=1 ; 
-+		SAE= ; 
-+		INTERNAL_JACK=; 
-+		WITH_LADSPA=; 
-+		STRIP=all ; 
-+		APPNAME=Ardour ;
-+		shift ;;
-+	--allinone)
-+		SAE= ; 
-+		WITH_NLS= ; 
-+		INTERNAL_JACK=1; 
-+		WITH_LADSPA=1; 
-+		STRIP=all; 
-+		shift ;;
-+	--test) SAE= ; INTERNAL_JACK=; WITH_LADSPA=; STRIP=all ; shift ;;
-+
-+	#
-+	# specific build flags
-+	#
-+
-+	--nojack) INTERNAL_JACK= ; shift ;;
-+	--noladspa) WITH_LADSPA= ; shift ;;
-+	--strip) STRIP=$2 ; shift ; shift ;;
-+	--sysdeps) PRINT_SYSDEPS=1; shift ;;
-+	--nls) WITH_NLS=1 ; shift ;;
-+	--external_jack) EXTERNAL_JACK=$2; shift ; shift ;;
-+
-+	*)
-+		#catch all for unknown arguments
-+		echo ""
-+		echo "!!! ERROR !!! - Unknown argument $1"
-+		echo ""
-+		exit 1
-+		;;
-+	esac
-+done
-+
-+if test x$STRIP != xall -a x$STRIP != xnone -a x$STRIP != xsome ; then
-+	echo "Unknown strip option \"$STRIP\""
-+	echo "Legal values are: all, none, some"
-+	exit 1
-+fi
-+
-+if [ x$EXTERNAL_JACK != x -a x$INTERNAL_JACK != x ] ; then
-+	echo "It makes no sense to package JACK internally and externally. Please pick one."
-+fi
-+
-+release_version=`grep -m 1 '^ardour_version' ../../SConstruct | cut -d' ' -f 3 | sed "s/'//g"`
-+svn_version=`grep -m 1 'svn_revision =' ../../libs/ardour/svn_revision.cc | cut -d' ' -f 6 | sed 's/[";]//g'`
-+echo "Version is $release_version / $svn_version"
-+info_string="$release_version/$svn_version built on `hostname` by `whoami` on `date`"
-+echo "Info string is $info_string"
-+
-+# Figure out our CPU type
-+case `uname -m` in
-+	i[3456789]86|x86|i86pc)
-+		echo "Architecture is x86"
-+		ARCH='x86'
-+		ARCH_BITS='32-bit'
-+		;;
-+	x86_64|amd64|AMD64)
-+		echo "Architecture is x86_64"
-+		ARCH='x86_64'
-+		ARCH_BITS='64-bit'
-+		;;
-+	*)
-+		echo ""
-+		echo "ERROR - Unknown architecture `uname -m`"
-+		echo ""
-+		exit 1
-+		;;
-+esac
-+
-+# Figure out the Build Type
-+if grep -q "DEBUG = True" ../../scache.conf; then
-+	DEBUG="T"
-+else
-+	DEBUG="F"
-+fi
-+
-+if [ x$DEBUG = xT ]; then
-+    BUILDTYPE="dbg"
-+    if [ x$STRIP = xall ] ; then
-+        echo "A debug build with --strip all makes no sense - STRIP reset to \"some\""
-+        STRIP=some
-+    fi
-+fi
-+
-+
-+# setup directory structure
-+
-+if [ -z "${BUILDTYPE}" ]; then
-+	APPDIR=${APPNAME}_${ARCH}-${release_version}_${svn_version}
-+	APP_VER_NAME=${APPNAME}-${release_version}_${svn_version}
-+else
-+	APPDIR=${APPNAME}_${ARCH}-${release_version}_${svn_version}-${BUILDTYPE}
-+	APP_VER_NAME=${APPNAME}-${release_version}_${svn_version}-${BUILDTYPE}
-+fi
-+
-+APPBIN=$APPDIR/bin
-+APPLIB=$APPDIR/lib
-+Libraries=$APPLIB
-+Etc=$APPDIR/etc
-+Shared=$APPDIR/share
-+Plugins=$APPLIB/plugins
-+Surfaces=$APPLIB/surfaces
-+Panners=$APPLIB/panners
-+Locale=$Shared/locale
-+Modules=$Libraries/modules
-+Loaders=$Libraries/loaders
-+
-+
-+if [ x$PRINT_SYSDEPS != x ] ; then
-+#
-+# print system dependencies
-+#
-+
-+	for file in $APPBIN/* $Libraries/* $Modules/* $Plugins/*.so ; do 
-+		if ! file $file | grep -qs Mach-O ; then
-+			continue
-+		fi
-+		otool -L $file | awk '{print $1}' | egrep -v "(^@executable_path|^Ardour[0-9][.0-9]*.app)" 
-+	done | sort | uniq
-+	exit 0
-+fi
-+
-+echo "Removing old $APPDIR tree ..."
-+rm -rf $APPDIR/
-+
-+echo "Building new app directory structure ..."
-+
-+# only bother to make the longest paths
-+
-+mkdir -p $APPDIR
-+mkdir -p $APPBIN
-+mkdir -p $APPLIB
-+mkdir -p $Etc
-+mkdir -p $Plugins
-+mkdir -p $Modules
-+mkdir -p $Loaders
-+mkdir -p $Shared
-+mkdir -p $Locale
-+mkdir -p $Surfaces
-+mkdir -p $Panners
-+mkdir -p $Shared/templates
-+mkdir -p $Shared/doc
-+
-+# maybe set variables
-+ENVIRONMENT=environment
-+rm -f $ENVIRONMENT
-+touch $ENVIRONMENT
-+
-+if test x$SAE != x ; then
-+	echo "export ARDOUR_SAE=true" >> $ENVIRONMENT
-+	#
-+	# current default for SAE version is German keyboard layout without a keypad
-+	#
-+	echo export ARDOUR_KEYBOARD_LAYOUT=de-nokeypad >> $ENVIRONMENT
-+	echo export ARDOUR_UI_CONF=ardour2_ui_sae.conf >> $ENVIRONMENT
-+	echo export ARDOUR2_UI_RC=ardour2_ui_dark_sae.rc >> $ENVIRONMENT
-+elif test x$MIXBUS != x ; then
-+	echo export ARDOUR_MIXBUS=true >> $ENVIRONMENT
-+	#
-+	# current default for MIXBUS version is US keyboard layout without a keypad
-+	#
-+	echo export ARDOUR_KEYBOARD_LAYOUT=us-nokeypad >> $ENVIRONMENT
-+	echo export ARDOUR_UI_CONF=ardour2_ui.conf >> $ENVIRONMENT
-+	echo export ARDOUR2_UI_RC=ardour2_ui_dark.rc >> $ENVIRONMENT
-+fi
-+
-+#
-+# if we're not going to bundle JACK, make sure we can find
-+# jack in the places where it might be
-+#
-+
-+echo export 'PATH=/usr/local/bin:/opt/bin:$PATH' >> $ENVIRONMENT
-+
-+# create startup helper script
-+
-+sed -e "/^%ENV%/r $ENVIRONMENT" -e '/^%ENV%/d' -e 's/%VER%/'"${release_version}"'/' < ardour.sh.in > $APPBIN/ardour2
-+rm $ENVIRONMENT && chmod 775 $APPBIN/ardour2
-+MAIN_EXECUTABLE=ardour-$release_version
-+
-+echo "Copying ardour executable ...."
-+cp ../../gtk2_ardour/$MAIN_EXECUTABLE $APPBIN
-+if test x$STRIP = xall ; then
-+	strip $APPBIN/$MAIN_EXECUTABLE
-+fi
-+
-+# copy locale files
-+if test x$WITH_NLS != x ; then
-+	echo "NLS support ..."
-+	echo "I hope you remembered to run scons msgupdate!"
-+	LINGUAS=
-+	files=`find ../../gtk2_ardour/ -name "*.mo"`
-+
-+	if [ -z "$files" ]; then
-+		echo ""
-+		echo "!!!! WARNING !!!! - Did not find any .mo files in ../../gtk2_ardour"
-+		echo ""
-+	fi
-+ 
-+	for file in $files 
-+	do
-+		echo $file
-+		lang=`basename $file | sed 's/\.mo//'`
-+		mkdir -p $Locale/$lang/LC_MESSAGES
-+		cp $file $Locale/$lang/LC_MESSAGES/gtk2_ardour.mo
-+		LINGUAS="$LINGUAS $lang"
-+	done
-+
-+	files=`find ../../libs/ardour/ -name "*.mo"`
-+
-+	if [ -z "$files" ]; then
-+		echo ""
-+		echo "!!!! WARNING !!!! - Did not find any .mo files in ../../libs/ardour"
-+		echo ""
-+	fi
-+
-+	for file in $files 
-+	do
-+		echo $file
-+		lang=`basename $file | sed 's/\.mo//'`
-+		mkdir -p $Locale/$lang/LC_MESSAGES
-+		cp $file $Locale/$lang/LC_MESSAGES/libardour.mo
-+	done
-+
-+	GTK_MESSAGES="atk10.mo gdk-pixbuf.mo gtk20-properties.mo gtk20.mo atk10.mo glib20.mo"
-+	LOCALEROOT=/usr/share/locale
-+
-+	for l in $LINGUAS ; do
-+		echo "Copying GTK i18n files for $l..."
-+		for MO in $GTK_MESSAGES ; do 
-+			if [ -f $LOCALEROOT/$l/LC_MESSAGES/$MO ] ; then
-+				cp $LOCALEROOT/$l/LC_MESSAGES/$MO $Locale/$l/LC_MESSAGES
-+			else
-+				# try with just the language spec
-+				just_lang=`echo $l | sed 's/_[A-Z][A-Z]$//'`
-+				if [ -f $LOCALEROOT/$just_lang/LC_MESSAGES/$MO ] ; then
-+					cp $LOCALEROOT/$just_lang/LC_MESSAGES/$MO $Locale/$just_lang/LC_MESSAGES
-+				fi
-+			fi
-+		done
-+	done
-+else
-+	echo "Skipping NLS support"
-+fi
-+
-+### Find gtk ###
-+GTKROOT=`pkg-config --libs-only-L gtk+-2.0 | sed -e "s/-L//" -e "s/[[:space:]]//g"`
-+if [ ! -z "$GTKROOT" ]; then
-+	echo "Found GTKROOT using pkg-config"
-+elif [ -d /usr/lib/gtk-2.0 ]; then
-+	GTKROOT="/usr/lib"
-+elif [ -d /usr/local/lib/gtk-2.0 ]; then
-+	GTKROOT="/usr/local/lib"
-+else
-+	echo ""
-+	echo "!!! ERROR !!! - Unable to locate gtk-2.0 directory. Packager will exit"
-+	echo ""
-+	exit 1
-+fi
-+
-+echo "GTKROOT is ${GTKROOT}"
-+versionDir=`ls ${GTKROOT}/gtk-2.0/ | grep "[0-9]*\.[0-9]*\.[0-9]*"`
-+
-+num=0
-+for name in $versionDir ; do
-+	num=$(($num + 1))
-+done
-+
-+if [ $num -eq 1 ]; then
-+	GTKLIB=${GTKROOT}/gtk-2.0/$versionDir
-+	echo "GTKLIB is ${GTKLIB}"
-+else
-+	echo ""
-+	echo "!!! ERROR !!! - More than one gtk-2.0 version found in ${GTKROOT}/gtk-2.0/  ( $versionDir ). Packager will exit"
-+	echo ""
-+	exit 1
-+fi
-+
-+
-+### Find pango ###
-+PANGOROOT=`pkg-config --libs-only-L pango | sed -e "s/-L//" -e "s/[[:space:]]//g"`
-+if [ ! -z "$PANGOROOT" ]; then
-+	echo "Found PANGOROOT using pkg-config"
-+elif [ -d /usr/lib/pango ]; then
-+	PANGOROOT="/usr/lib"
-+elif [ -d /usr/local/lib/pango ]; then
-+	PANGOROOT="/usr/local/lib"
-+else
-+	echo ""
-+	echo "!!! ERROR !!! - Unable to locate pango directory. Packager will exit"
-+	echo ""
-+	exit 1
-+fi
-+
-+echo "PANGOROOT is ${PANGOROOT}"
-+versionDir=`ls ${PANGOROOT}/pango/ | grep "[0-9]*\.[0-9]*\.[0-9]*"`
-+
-+num=0
-+for name in $versionDir ; do
-+	num=$(($num + 1))
-+done
-+
-+if [ $num -eq 1 ]; then
-+	PANGOLIB=${PANGOROOT}/pango/$versionDir
-+	echo "PANGOLIB is ${PANGOLIB}"
-+else
-+	echo ""
-+	echo "!!! ERROR !!! - More than one pango version found in ${PANGOROOT}/pango/  ( $versionDir ). Packager will exit"
-+	echo ""
-+	exit 1
-+fi
-+
-+
-+### Find gdk-pixbuf ###
-+GDKPIXBUFROOT=`pkg-config --libs-only-L gdk-pixbuf-2.0 | sed -e "s/-L//" -e "s/[[:space:]]//g"`
-+if [ ! -z "$GDKPIXBUFROOT" ]; then
-+	echo "Found GDKPIXBUFROOT using pkg-config"
-+elif [ -d /usr/lib/gdk-pixbuf-2.0 ]; then
-+	GDKPIXBUFROOT="/usr/lib/gdk-pixbuf-2.0"
-+elif [ -d /usr/local/lib/gdk-pixbuf-2.0 ]; then
-+	GDKPIXBUFROOT="/usr/local/lib/gdk-pixbuf-2.0"
-+elif [ -d ${GTKLIB}/loaders ]; then  #odd ball case
-+	GDKPIXBUFROOT=${GTKROOT}
-+	GDKPIXBUFLIB=${GTKLIB}
-+else
-+	echo ""
-+	echo "!!! ERROR !!! - Unable to locate gdk-pixbuf-2.0 directory. Packager will exit"
-+	echo ""
-+	exit 1
-+fi
-+
-+echo "GDKPIXBUFROOT is ${GDKPIXBUFROOT}"
-+
-+if [ -z ${GDKPIXBUFLIB} ]; then
-+	versionDir=`ls ${GDKPIXBUFROOT}/gdk-pixbuf-2.0/ | grep "[0-9]*\.[0-9]*\.[0-9]*"`
-+
-+	num=0
-+	for name in $versionDir ; do
-+		num=$(($num + 1))
-+	done
-+
-+	if [ $num -eq 1 ]; then
-+		GDKPIXBUFLIB=${GDKPIXBUFROOT}/gdk-pixbuf-2.0/$versionDir
-+		echo "GDKPIXBUFLIB is ${GDKPIXBUFLIB}"
-+	else
-+		echo ""
-+		echo "!!! ERROR !!! - More than one gdk-pixbuf-2.0 version found in ${GDKPIXBUFROOT}/pango/  ( $versionDir ). Packager will exit"
-+		echo ""
-+		exit 1
-+	fi
-+fi
-+
-+
-+
-+echo "Copying all Pango modules ..."
-+cp -R $PANGOLIB/modules/*.so $Modules
-+
-+echo "Copying all GDK Pixbuf loaders ..."
-+cp -R $GDKPIXBUFLIB/loaders/*.so $Loaders
-+
-+pango-querymodules | sed "s?$PANGOLIB/?@ROOTDIR@/?" > $Etc/pango.modules.in
-+gdk-pixbuf-query-loaders | sed "s?$GDKPIXBUFLIB/?@ROOTDIR@/?" > $Etc/gdk-pixbuf.loaders.in
-+
-+# We sort of rely on clearlooks, so include a version
-+# this one is special - we will set GTK_PATH to $Libraries/clearlooks
-+
-+if [ ! -e ${GTKLIB}/engines/libclearlooks.so ]; then
-+	echo ""
-+	echo "!!! ERROR !!! - not able to locate libclearlooks.so"
-+	echo ""
-+	echo "Packager with exit"
-+	exit 1
-+fi
-+
-+echo "Copying clearlooks ..."
-+cp ${GTKLIB}/engines/libclearlooks.so $Libraries
-+mkdir -p $Libraries/clearlooks/engines
-+(cd $Libraries/clearlooks/engines && ln -s ../../libclearlooks* libclearlooks.so )
-+
-+# LADSPA
-+if test x$WITH_LADSPA != x ; then
-+	if test x$SAE != x ; then
-+		plugdir=sae_ladspa
-+	elif test x$MIXBUS != x ; then
-+		plugdir=mixbus_ladspa
-+	else
-+		plugdir=ladspa
-+	fi
-+	echo "Copying `ls $plugdir | wc -l` plugins ..."
-+	if [ -d $plugdir ] ; then
-+		cp -r $plugdir/* $Plugins
-+	fi
-+fi
-+
-+# XXX STILL NEED TO DO PANNERS FOR TRUNK
-+cp ../../libs/surfaces/*/libardour_*.so* $Surfaces
-+# hack ... move libardour_cp back into Libraries
-+mv $Surfaces/libardour_cp.so* $Libraries
-+
-+# VAMP plugins that we use
-+cp ../../libs/vamp-plugins/libardourvampplugins.so* $Libraries
-+
-+OURLIBDIR=../../libs
-+OURLIBS=$OURLIBDIR/vamp-sdk:$OURLIBDIR/surfaces/control_protocol:$OURLIBDIR/ardour:$OURLIBDIR/midi++2:$OURLIBDIR/pbd:$OURLIBDIR/rubberband:$OURLIBDIR/soundtouch:$OURLIBDIR/gtkmm2ext:$OURLIBDIR/sigc++2:$OURLIBDIR/glibmm2:$OURLIBDIR/gtkmm2/atk:$OURLIBDIR/gtkmm2/pango:$OURLIBDIR/gtkmm2/gdk:$OURLIBDIR/gtkmm2/gtk:$OURLIBDIR/libgnomecanvasmm:$OURLIBDIR/libsndfile
-+
-+echo $OURLIBS${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
-+
-+checkedIdx=0
-+deplibs=
-+
-+while [ true ] ; do 
-+	missing=false
-+	filelist=`find $APPLIB/ -type f`
-+	filelist="$APPBIN/$MAIN_EXECUTABLE $filelist"
-+
-+	for file in $filelist  ; do 
-+		if ! file $file | grep -qs ELF ; then
-+			continue
-+		fi
-+
-+		# speed this up a bit by not checking things multiple times.
-+		for i in "${depCheckedList[@]}"; do
-+			if [ $i == $file ]; then
-+				continue 2
-+			fi
-+		done
-+		depCheckedList[$checkIdx]=$file
-+		checkIdx=$(($checkIdx + 1))
-+		
-+		# do not include libjack
-+		deps=`LD_LIBRARY_PATH=$OURLIBS${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} ldd $file | awk '{print $3}'`
-+
-+		# LD_LIBRARY_PATH=$OURLIBS${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} ldd $file | egrep "(/opt/|/local/|libs/|/usr/lib|/gtk)" | grep -v 'libjack\.'
-+		echo -n "."
-+		for dep in $deps ; do
-+			if test "not" = ${dep}; then 
-+				echo ""
-+				echo "!!! ERROR !!! - Missing dependant library for $file."
-+				echo ""
-+				(LD_LIBRARY_PATH=$OURLIBS${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} ldd $file)
-+				echo ""
-+				echo "!!! ERROR !!! - See Above"
-+				exit 1
-+			fi
-+
-+			# don't use anything mapped at a specific address
-+			if echo $dep | grep -qs '0x' ; then continue; fi
-+			# don't include /lib
-+			if echo $dep | grep -qs "^/lib/" ; then continue; fi
-+			# don't include jack
-+			if echo $dep | grep -qs libjack ; then continue; fi
-+			# don't include any X Window libraries
-+			if echo $dep | grep -qs libX ; then continue; fi  
-+			if echo $dep | grep -qs libxcb ; then continue; fi  
-+			# don't include libc
-+			if echo $dep | grep -qs 'libc\.' ; then continue; fi
-+			# don't include libstdc++
-+			if echo $dep | grep -qs libstdc++ ; then continue; fi
-+
-+			base=`basename $dep`
-+			if ! test -f $Libraries/$base; then
-+				parent=$(basename ${file})
-+				if echo $dep | grep -sq '^libs' ; then
-+					echo "Copying dependant lib ../../$dep    (required by ${parent})"
-+					cp ../../$dep $Libraries
-+				else
-+					echo "Copying dependant lib $dep    (required by ${parent})"
-+					cp $dep $Libraries
-+				fi
-+				if echo $dep | grep -sq '^/' ; then
-+					# absolute path, candidate for stripping
-+					deplibs="$deplibs $base"
-+				fi
-+				missing=true
-+			fi
-+		done
-+	done
-+	if test x$missing = xfalse ; then
-+		# everything has been found
-+		break
-+	fi
-+done
-+echo
-+
-+# strip libraries
-+if test x$STRIP = xall ; then
-+    echo Stripping all libraries
-+    find $APPLIB/ -name "*.so*" | xargs strip
-+elif test x$STRIP = xsome ; then
-+    echo Stripping dependent libraries
-+    for l in $deplibs ; do
-+        strip $APPLIB/$l
-+    done
-+fi
-+find $APPLIB/ -name "*.so*" | xargs chmod a+rx
-+
-+echo "Copying other stuff to $APPDIR  ..."
-+
-+cp ../../gtk2_ardour/ergonomic-us.bindings	$Etc
-+cp ../../gtk2_ardour/mnemonic-us.bindings  $Etc
-+cp ../../gtk2_ardour/SAE-de-keypad.bindings  $Etc
-+cp ../../gtk2_ardour/SAE-de-nokeypad.bindings  $Etc
-+cp ../../gtk2_ardour/SAE-us-keypad.bindings  $Etc
-+cp ../../gtk2_ardour/SAE-us-nokeypad.bindings  $Etc
-+cp ../../gtk2_ardour/ardour.menus $Etc
-+cp ../../gtk2_ardour/ardour-sae.menus $Etc
-+if test x$SAE != x ; then
-+	cp ../../ardour_system_sae.rc $Etc/ardour_system.rc
-+	echo cp ../../ardour_system_sae.rc $Etc/ardour_system.rc
-+	cp ../../instant.xml.sae $Etc/instant.xml
-+	echo cp ../../instant.xml.sae $Etc/instant.xml
-+else
-+	cp ../../ardour_system.rc $Etc/ardour_system.rc
-+	echo cp ../../ardour_system.rc $Etc/ardour_system.rc
-+	cp ../../instant.xml $Etc/instant.xml
-+	echo cp ../../instant.xml $Etc/instant.xml
-+fi
-+cp ../../gtk2_ardour/ardour2_ui_sae.conf $Etc
-+cp ../../gtk2_ardour/ardour2_ui_default.conf $Etc
-+cp ../../gtk2_ardour/ardour2_ui_default.conf $Etc/ardour2_ui.conf
-+cp ../../gtk2_ardour/ardour2_ui_light.rc $Etc
-+cp ../../gtk2_ardour/ardour2_ui_dark.rc $Etc
-+cp ../../gtk2_ardour/ardour2_ui_light_sae.rc $Etc
-+cp ../../gtk2_ardour/ardour2_ui_dark_sae.rc $Etc
-+
-+cp -r ../../gtk2_ardour/icons $Etc
-+cp -r ../../gtk2_ardour/pixmaps $Etc
-+
-+#
-+# put sooper sekrit ingredients here and they will be copied
-+#
-+
-+if [ -d specialSauce ] ; then
-+	cp -r specialSauce $Etc
-+fi
-+
-+# share stuff
-+
-+cp -R ../../gtk2_ardour/splash.png $Shared
-+cp ../../templates/*.template $Shared/templates/
-+
-+# go through and recursively remove any .svn dirs in the bundle
-+for svndir in `find $APPDIR -name .svn -type d`; do
-+	rm -rf $svndir
-+done
-+
-+#
-+# Add any documentation to the top level of the package
-+# 
-+
-+if [ x$SAE != x ] ; then
-+	
-+	# SAE packaging
-+	
-+	echo "Adding SAE documentation"
-+	cp HowToInstallArdourSAE.pdf "$Shared/doc/How To Install Ardour SAE.pdf"
-+	cp SAE-de-keypad.pdf "$Shared/doc/Ardour SAE Shortcuts (keypad).pdf"
-+	cp SAE-de-nokeypad.pdf "$Shared/doc/Ardour SAE Shortcuts.pdf"
-+	
-+elif [ x$MIXBUS != x ] ; then
-+
-+	# Mixbus packaging
-+
-+	echo "Adding Mixbus documentation"
-+	cp MixBus_Install_QuickStart.pdf "$Shared/doc/Mixbus Install & Quick Start Guide.pdf"
-+	
-+	if [ -x $EXTERNAL_JACK != x ] ; then
-+		cp $EXTERNAL_JACK $PRODUCT_PKG_DIR
-+	fi
-+fi
-+
-+#
-+# Add the uninstaller
-+#
-+sed -e "s/%REPLACE_PGM%/${APPNAME}/" -e "s/%REPLACE_VENDOR%/${VENDOR}/" -e "s/%REPLACE_VERSION%/${release_version}/" -e "s/%REPLACE_BUILD%/${svn_version}/" -e "s/%REPLACE_TYPE%/${BUILDTYPE}/" < uninstall.sh.in > $APPBIN/${APP_VER_NAME}.uninstall.sh
-+chmod a+x $APPBIN/${APP_VER_NAME}.uninstall.sh
-+
-+#Sanity Check file
-+if [ -e ../sanity_check/sanityCheck ]; then
-+	cp ../sanity_check/sanityCheck $APPBIN
-+else
-+	echo "!!!ERROR !!! sanityCheck program is missing. packager will exit without being complete"
-+	exit 1
-+fi
-+
-+echo "Building tarball ..."
-+
-+rm -f $APPDIR.tar.bz2
-+tar -cjf $APPDIR.tar.bz2 $APPDIR
-+
-+echo "Calculating bundle size"
-+du -sb $APPDIR/  | awk '{print $1}' > $APPDIR.size
-+
-+rm -rf $APPDIR/
-+
-+echo "Done."
-+
-diff --git a/tools/linux_packaging/buildenv b/tools/linux_packaging/buildenv
-new file mode 100644
-index 0000000..5d94591
---- /dev/null
-+++ b/tools/linux_packaging/buildenv
-@@ -0,0 +1,8 @@
-+GTK_PREFIX_DIR=/gtk/will/search/here
-+
-+if ! echo $LD_LIBRARY_PATH | grep -qs $GTK_PREFIX_DIR ; then
-+   LD_LIBRARY_PATH=${GTK_PREFIX_DIR}/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
-+   PATH=${GTK_PREFIX_DIR}/bin:$PATH
-+   PKG_CONFIG_PATH=${GTK_PREFIX_DIR}/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}
-+fi
-+
-diff --git a/tools/linux_packaging/install.sh b/tools/linux_packaging/install.sh
-new file mode 100755
-index 0000000..33863ee
---- /dev/null
-+++ b/tools/linux_packaging/install.sh
-@@ -0,0 +1,25 @@
-+#!/bin/sh
-+
-+# Make sure we have a terminal for the user to see and then run
-+# the real install script.
-+
-+# Some systems don't correctly set the PWD when a script is double-clicked,
-+# so go ahead and figure out our path and make sure we are in that directory.
-+
-+SAVED_PWD=$PWD
-+PKG_PATH=$(dirname $(readlink -f $0))
-+cd ${PKG_PATH}
-+
-+if [ -z "$TERM" ] || [ "$TERM" = "dumb" ]; then
-+	if which xterm > /dev/null; then
-+		exec xterm -e ${PKG_PATH}/.stage2.run
-+	elif which gnome-terminal > /dev/null; then
-+		exec gnome-terminal -e ${PKG_PATH}/.stage2.run
-+	elif which konsole > /dev/null; then
-+		exec konsole -e ${PKG_PATH}/.stage2.run
-+	fi
-+else
-+	${PKG_PATH}/.stage2.run
-+fi
-+
-+cd ${SAVED_PWD}
-diff --git a/tools/linux_packaging/package b/tools/linux_packaging/package
-new file mode 100755
-index 0000000..934ce36
---- /dev/null
-+++ b/tools/linux_packaging/package
-@@ -0,0 +1,176 @@
-+#!/bin/bash
-+
-+# package
-+
-+# This will collect up the x86 and x86_64 bundles created by build
-+# and package them together with an installer script.
-+
-+BUILDTYPE=""
-+SINGLE_ARCH="F"
-+X86_BUNDLE_OK="F"
-+X86_64_BUNDLE_OK="F"
-+
-+
-+if [ $# -eq 0 ] ; then
-+	echo ""	 
-+	echo "ERROR - Please specify build type"
-+	echo "	  --public"
-+	echo "	  --sae"
-+	echo ""	 
-+	exit 1
-+fi
-+
-+while [ $# -gt 0 ] ; do
-+	echo "arg = $1"
-+	case $1 in
-+
-+	#
-+	# top level build targets
-+	#
-+
-+	--sae)
-+		APPNAME=Ardour ;
-+		shift ;;
-+	--mixbus)
-+		APPNAME=Mixbus ;
-+		shift ;;
-+	--public)
-+		APPNAME=Ardour ;
-+		shift ;;
-+
-+	--singlearch) SINGLE_ARCH="T" ; shift ;;
-+
-+	*)
-+		#catch all for unknown arguments
-+		echo ""
-+		echo "!!! ERROR !!! - Unknown argument $1"
-+		echo ""
-+		exit 1
-+		;;
-+	esac
-+done
-+
-+
-+# Figure out the Build Type
-+if grep -q "DEBUG = True" ../../scache.conf; then
-+	DEBUG="T"
-+else
-+	DEBUG="F"
-+fi
-+
-+if [ x$DEBUG = xT ]; then
-+	BUILDTYPE="dbg"
-+fi
-+
-+release_version=`grep -m 1 '^ardour_version' ../../SConstruct | cut -d' ' -f 3 | sed "s/'//g"`
-+svn_version=`grep -m 1 'svn_revision =' ../../libs/ardour/svn_revision.cc | cut -d' ' -f 6 | sed 's/[";]//g'`
-+
-+X86_BUNDLE="${APPNAME}_x86-${release_version}_${svn_version}"
-+X86_64_BUNDLE="${APPNAME}_x86_64-${release_version}_${svn_version}"
-+
-+if [ ! -z ${BUILDTYPE} ]; then
-+	X86_BUNDLE="${X86_BUNDLE}-${BUILDTYPE}"
-+	X86_64_BUNDLE="${X86_64_BUNDLE}-${BUILDTYPE}"
-+fi 
-+
-+
-+if [ ! -e ${X86_BUNDLE}.tar.bz2 ] ; then
-+	echo ""
-+	echo "Can't locate x86 bundle file ${X86_BUNDLE}.tar.bz2"
-+	echo ""
-+elif [ ! -e ${X86_BUNDLE}.size ] ; then
-+	echo ""
-+	echo "Can't locate x86 bundle size file ${X86_BUNDLE}.size"
-+	echo ""
-+else
-+	X86_BUNDLE_OK="T"
-+fi
-+
-+if [ ! -e ${X86_64_BUNDLE}.tar.bz2 ]; then
-+	echo ""
-+	echo "Can't locate x86_64 bundle file ${X86_64_BUNDLE}.tar.bz2"
-+	echo ""
-+elif [ ! -e ${X86_64_BUNDLE}.size ]; then
-+	echo ""
-+	echo "Can't locate x86 bundle size file ${X86_BUNDLE}.size"
-+	echo ""
-+else
-+	X86_64_BUNDLE_OK="T"
-+fi
-+
-+
-+if [ "${X86_BUNDLE_OK}" = "F" ] || [ "${X86_64_BUNDLE_OK}" = "F" ]; then
-+	if [ "${X86_BUNDLE_OK}" = "${X86_64_BUNDLE_OK}" ]; then
-+		echo ""
-+		echo "!!! ERROR !!! - Can't locate bundle files ${X86_BUNDLE} or ${X86_64_BUNDLE}"
-+		echo ""
-+		exit 1
-+	elif [ "${SINGLE_ARCH}" = "T" ]; then
-+		echo ""
-+		echo "!!! Warning !!! - A single architecture package has been selected"
-+		echo ""
-+	else
-+		echo ""
-+		echo "!!! ERROR !!! - Missing bundle files."
-+		echo ""
-+		exit 1
-+	fi
-+fi
-+
-+
-+
-+if [ -z ${BUILDTYPE} ]; then
-+	if [ "${SINGLE_ARCH}" = "T" ]; then
-+		if [ "${X86_BUNDLE_OK}" = "T" ]; then
-+			PACKAGE="${APPNAME}_32bit-${release_version}_${svn_version}"
-+		else
-+			PACKAGE="${APPNAME}_64bit-${release_version}_${svn_version}"
-+		fi
-+	else
-+		PACKAGE="${APPNAME}-${release_version}_${svn_version}"
-+	fi
-+else
-+	if [ "${SINGLE_ARCH}" = "T" ]; then
-+		if [ "${X86_BUNDLE_OK}" = "T" ]; then
-+			PACKAGE="${APPNAME}_32bit-${release_version}_${svn_version}-${BUILDTYPE}"
-+		else
-+			PACKAGE="${APPNAME}_64bit-${release_version}_${svn_version}-${BUILDTYPE}"
-+		fi
-+	else
-+		PACKAGE="${APPNAME}-${release_version}_${svn_version}-${BUILDTYPE}"
-+	fi
-+fi 
-+
-+
-+echo "Cleaning up any old package files for this build"
-+#Get rid of any old packages of this same name.
-+rm -f ${PACKAGE}.tar.bz2
-+rm -rf ${PACKAGE}
-+
-+
-+echo "Creating new package dir..."
-+mkdir ${PACKAGE}
-+
-+if [ "${X86_BUNDLE_OK}" = "T" ]; then
-+	mv ${X86_BUNDLE}.tar.bz2 ${PACKAGE}
-+	mv ${X86_BUNDLE}.size ${PACKAGE}/.${X86_BUNDLE}.size
-+fi
-+
-+if [ "${X86_64_BUNDLE_OK}" = "T" ]; then
-+	mv ${X86_64_BUNDLE}.tar.bz2 ${PACKAGE}
-+	mv ${X86_64_BUNDLE}.size ${PACKAGE}/.${X86_64_BUNDLE}.size
-+fi
-+
-+cp install.sh ${PACKAGE}
-+cp stage2.run ${PACKAGE}/.stage2.run
-+cp README ${PACKAGE}
-+
-+echo "Creating tarball..."
-+tar -cf ${PACKAGE}.tar ${PACKAGE}
-+
-+echo "Clean up"
-+rm -rf ${PACKAGE}
-+
-+echo ""
-+echo "Done"
-+echo ""
-diff --git a/tools/linux_packaging/stage2.run b/tools/linux_packaging/stage2.run
-new file mode 100755
-index 0000000..7f6eafd
---- /dev/null
-+++ b/tools/linux_packaging/stage2.run
-@@ -0,0 +1,621 @@
-+#!/bin/sh
-+
-+####################################
-+#
-+#	stage2.run
-+#	Ardour/Mixbus bundle installer
-+#	Todd Naugle
-+#
-+###################################
-+
-+
-+
-+PGM_NAME="Ardour"
-+PGM_VENDOR="Ardour"
-+PGM_EXEC_FILE="ardour2"
-+
-+INSTALL_DEST_BASE="/opt"
-+
-+PGM_NAME_LOWER=$(echo $PGM_NAME | tr '[:upper:]' '[:lower:]')
-+
-+#### Global Variables ####
-+HAS_XDG="T"
-+
-+########################
-+# Function Definitions
-+########################
-+
-+VaildateYesNoQuestion ()
-+{
-+	# $1 = Question Text
-+	
-+	local INPUT_OK="n"
-+	local USER_INPUT=""
-+
-+	until test "y" = $INPUT_OK;
-+	do
-+		echo ""
-+		read -p "$1 [y/n]: " USER_INPUT
-+		echo ""
-+
-+		if [ ! -z $USER_INPUT ]; 
-+		then		
-+			if [ "Y" = $USER_INPUT -o "y" = $USER_INPUT -o "n" = $USER_INPUT -o "N" = $USER_INPUT ];
-+			then
-+				INPUT_OK="y"
-+			fi
-+		fi
-+	done
-+	
-+	echo $USER_INPUT | tr '[:upper:]' '[:lower:]'
-+	
-+}
-+
-+SystemInstall ()
-+{
-+
-+	# Determine which software install app to use and then install requested package
-+	# $1 = Package Name
-+
-+	if which yum > /dev/null;
-+	then
-+		${SUPER} yum -y install $1
-+		rtrn=$?
-+
-+		if [ $rtrn -ne 0 ];
-+		then
-+			echo ""
-+			echo "!!! ERROR !!! yum install failed for an unknown reason."
-+			echo "Please install package $1 after this installer completes."
-+			echo ""
-+		fi
-+
-+	elif which apt-get > /dev/null;
-+	then
-+		${SUPER} apt-get -y install $1
-+		rtrn=$?
-+
-+		if [ $rtrn -ne 0 ];
-+		then
-+			echo ""
-+			echo "!!! ERROR !!! apt-get install failed for an unknown reason."
-+			echo "Please install package $1 after this installer completes."
-+			echo ""
-+		fi
-+
-+	else
-+		echo ""
-+		echo "!!! ERROR !!! - Not able to detect which software install tool to use (yum or apt-get)."
-+		echo "Please install package $1 using the system software install tool."
-+		echo ""
-+		rtrn=1
-+	fi
-+	
-+	return $rtrn
-+
-+}
-+
-+########################################################################
-+#                                 Main
-+########################################################################
-+
-+# If you double click a script, some systems don't get the PWD correct.
-+# Force it to be correct
-+PKG_PATH=$(dirname $(readlink -f $0))
-+cd ${PKG_PATH}
-+
-+echo ""
-+echo "Welcome to the ${PGM_NAME} installer"
-+echo ""
-+
-+#############################
-+# Check for root privileges
-+#############################
-+
-+SUPER=""
-+
-+if [ "$(id -u)" != "0" ]; then
-+
-+	if ! which sudo > /dev/null;
-+	then
-+		echo ""
-+		echo "!!! ERROR !!!"
-+		echo ""
-+		echo "The installer requires root privileges. It is currently not"
-+		echo "running as root AND the program sudo is missing from this system."
-+		echo ""
-+		echo "Please correct this by installing and configuring sudo or running"
-+		echo "the installer as root."
-+		echo ""
-+		read -p "Press ENTER to exit installer:" BLAH
-+		exit 1
-+	fi
-+
-+	if ! sudo date;
-+	then
-+		echo ""
-+		echo "!!! ERROR !!!"
-+		echo ""
-+		echo "Either you don't know the root password or the user is not allowed to sudo"
-+		echo "Please correct this and run the installer again"
-+		echo "(hint: use visudo to edit sudoers file)"
-+		echo ""
-+		read -p "Press ENTER to exit installer:" BLAH
-+		exit 1
-+	fi
-+	SUPER="sudo"
-+else
-+	echo ""
-+	echo "!!! Warning !!!"
-+	echo ""
-+	echo "The installer is running as the root user which is not the prefered method."
-+	echo "There are checks run at the end of the installer to help ensure proper operation"
-+	echo "of ${PGM_NAME} (realtime priviledges, memory locking, frequency scaling)."
-+	echo "Running as root will invalidate these tests."
-+	echo ""
-+	read -p "Press ENTER to continue:" BLAH
-+	
-+fi
-+
-+############################
-+# Determine processor type
-+############################
-+
-+case `uname -m` in
-+	i[3456789]86|x86|i86pc)
-+		echo "Architecture is x86"
-+		ARCH='x86'
-+		;;
-+	x86_64|amd64|AMD64)
-+		echo "Architecture is x86_64"
-+		ARCH='x86_64'
-+		;;
-+	*)
-+		echo ""
-+		echo "!!! ERROR !!! - Unknown architecture `uname -m`"
-+		echo ""
-+		read -p "Press ENTER to exit installer:" BLAH
-+		exit 1
-+		;;
-+esac
-+
-+####################
-+# Check disk space
-+####################
-+
-+# We have to check the current folder and the INSTALL_DEST_BASE just
-+# in case they are on different devices
-+echo "Checking for required disk space"
-+
-+if [ ! -e .${PGM_NAME}_${ARCH}-*.size ]; then
-+	echo ""
-+	echo "!!! ERROR !!! Can't locate .size file for ${ARCH} bundle."
-+	echo ""
-+	exit 1
-+else
-+	REQUIRED_BYTES=$(cat .${PGM_NAME}_${ARCH}-*.size)
-+
-+	#Check space in current folder
-+	FREE_BYTES=$(df -B 1 ${PKG_PATH} | grep / | awk '{print $4}')
-+
-+	if [ ${FREE_BYTES} -le ${REQUIRED_BYTES} ] ; then
-+		echo ""
-+		echo "!!! ERROR !!! - Insufficient disk space in ${PKG_PATH}"
-+		echo ""
-+		exit 1
-+	fi
-+
-+	#Check space in INSTALL_DEST_BASE
-+	FREE_BYTES=$(df -B 1 ${INSTALL_DEST_BASE} | grep / | awk '{print $4}')
-+
-+	if [ ${FREE_BYTES} -le ${REQUIRED_BYTES} ] ; then
-+		echo ""
-+		echo "!!! ERROR !!! - Insufficient disk space in ${INSTALL_DEST_BASE}"
-+		echo ""
-+		exit 1
-+	fi
-+fi
-+
-+#####################
-+# Unpack the bundle
-+#####################
-+
-+# untar the correct bundle for us to install
-+echo "Unpacking bundle for $ARCH"
-+
-+if [ ! -e ${PGM_NAME}_${ARCH}-*.tar.bz2 ]; then
-+	echo ""
-+	echo "!!! ERROR !!! Can't locate ${ARCH} bundle file."
-+	echo ""
-+	exit 1
-+fi
-+
-+tar -xjf ${PGM_NAME}_${ARCH}-*.tar.bz2
-+BUNDLE_DIR=$(basename `find -maxdepth 1 -type d -name "${PGM_NAME}_${ARCH}-*"`)
-+
-+
-+#######################
-+# Check for xdg utils
-+#######################
-+
-+XDG_MENU_VER=$(xdg-desktop-menu --version 2> /dev/null)
-+if [ -z "$XDG_MENU_VER" ];
-+then
-+	echo "System does not have xdg-desktop-menu installed"
-+	HAS_XDG="F"
-+fi
-+
-+XDG_ICON_VER=$(xdg-icon-resource --version 2> /dev/null)
-+if [ -z "$XDG_ICON_VER" ];
-+then
-+	echo "System does not have xdg-icon-resource installed"
-+	HAS_XDG="F"
-+fi
-+
-+#################################################
-+# Check if system libs are OK (libc, etc)
-+#################################################
-+
-+echo ""
-+echo "Checking system libs to see if they are compatible with ${PGM_NAME}."
-+echo ""
-+
-+LIB_ERROR="F"
-+LD_PATH=`pwd`/${BUNDLE_DIR}/lib
-+
-+# check the main App
-+LDD_RESULT=$(LD_LIBRARY_PATH=${LD_PATH} ldd ${BUNDLE_DIR}/bin/${PGM_NAME_LOWER}-* 2>&1 > /dev/null)
-+
-+if [ -n "$LDD_RESULT" ];
-+then
-+	echo "$LDD_RESULT"
-+	LIB_ERROR="T"
-+fi
-+	
-+# check the libs
-+LIB_FILES=$(find ${BUNDLE_DIR}/lib -name "*.so")
-+
-+for path in $LIB_FILES
-+do
-+	LDD_RESULT=$(LD_LIBRARY_PATH=${LD_PATH} ldd $path 2>&1 > /dev/null)
-+	if [ -n "$LDD_RESULT" ];
-+	then
-+		echo "$LDD_RESULT"
-+		LIB_ERROR="T"
-+	fi
-+done
-+
-+if test "T" = $LIB_ERROR;
-+then
-+	echo ""
-+	echo "!!! ERROR !!! - Missing library detected!"
-+	echo "This system does not have the correct libs to run ${PGM_NAME}."
-+	echo "Installation will not complete. Please use a compatible distro."
-+	echo ""
-+	read -p "Press ENTER to exit installer:" BLAH
-+	exit 1
-+fi
-+
-+################################
-+# Setup derived variables
-+################################
-+PGM_VERSION=$(echo ${BUNDLE_DIR} | awk 'BEGIN { FS = "-" } ; { print $2 }' | awk 'BEGIN { FS = "_"} ; { print $1}')
-+PGM_BUILD=$(echo ${BUNDLE_DIR} | awk 'BEGIN { FS = "-" } ; { print $2 }' | awk 'BEGIN { FS = "_"} ; { print $2}')
-+PGM_BUILDTYPE=$(echo ${BUNDLE_DIR} | awk 'BEGIN { FS = "-" } ; { print $3 }')
-+
-+if [ -z ${PGM_BUILDTYPE} ];
-+then
-+	PGM_FULL_NAME="${PGM_NAME}-${PGM_VERSION}_${PGM_BUILD}"
-+	ICON_NAME="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}"			#no dash between name and version since dash seperates vendor from program
-+	MENU_FILE="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}.desktop"	#no dash between name and version since dash seperates vendor from program
-+	DESKTOP_LINK_FILE="${PGM_NAME}_${PGM_VERSION}.desktop"
-+else
-+	PGM_FULL_NAME="${PGM_NAME}-${PGM_VERSION}_${PGM_BUILD}-${PGM_BUILDTYPE}"
-+	ICON_NAME="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}_${PGM_BUILDTYPE}"			#no dash between name and version since dash seperates vendor from program
-+	MENU_FILE="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}_${PGM_BUILDTYPE}.desktop"	#no dash between name and version since dash seperates vendor from program
-+	DESKTOP_LINK_FILE="${PGM_NAME}_${PGM_VERSION}_${PGM_BUILDTYPE}.desktop"
-+fi
-+
-+PGM_EXEC_PATH="${INSTALL_DEST_BASE}/${PGM_FULL_NAME}/bin/${PGM_EXEC_FILE}"
-+ICON_PATH="${INSTALL_DEST_BASE}/${PGM_FULL_NAME}/etc/icons"
-+MENU_FILE_PATH="${INSTALL_DEST_BASE}/${PGM_FULL_NAME}/share"
-+
-+	
-+
-+################################
-+# Install bundle and Menu/Link
-+################################
-+
-+if [ ! -d ${INSTALL_DEST_BASE} ];
-+then
-+	echo ""
-+	echo "!!! ERROR !!! - Installation location ${INSTALL_DEST_BASE} does not exist!"
-+	echo "Installation will not complete."
-+	echo ""
-+	read -p "Press ENTER to exit installer:" BLAH
-+	exit 1
-+fi
-+
-+# uninstall any older versions
-+UNINSTALLERS=$(find ${INSTALL_DEST_BASE} -maxdepth 1 -type f -name "${PGM_NAME}*.uninstall.sh")
-+if [ ! -z "$UNINSTALLERS" ];
-+then
-+	for i in $UNINSTALLERS; do
-+		echo ""
-+		echo "Found existing ${PGM_NAME} installation."
-+		
-+		ANSWER=$(VaildateYesNoQuestion "Do you want to run the uninstaller ${i} ?")
-+
-+		if test "y" = $ANSWER;
-+		then
-+			echo ""
-+			echo "Running uninstaller $i"
-+			
-+			${i}
-+			${SUPER} rm -f ${i}
-+		fi
-+	done
-+fi
-+
-+
-+# install 
-+
-+echo ""
-+echo "Installing ${PGM_NAME} ${PGM_VERSION} built from ${PGM_BUILD} in ${INSTALL_DEST_BASE}"
-+echo ""
-+
-+# Copy the new version in the install directory
-+${SUPER} mkdir ${INSTALL_DEST_BASE}/${PGM_FULL_NAME} 
-+${SUPER} cp -Rf	${BUNDLE_DIR}/* ${INSTALL_DEST_BASE}/${PGM_FULL_NAME}/
-+
-+# write the desktop/menu file
-+echo "[Desktop Entry]" > /tmp/${MENU_FILE}
-+echo "Encoding=UTF-8" >> /tmp/${MENU_FILE}
-+echo "Version=1.0" >> /tmp/${MENU_FILE}
-+echo "Type=Application" >> /tmp/${MENU_FILE}
-+echo "Terminal=false" >> /tmp/${MENU_FILE}
-+echo "Exec=${PGM_EXEC_PATH}" >> /tmp/${MENU_FILE}
-+if [ -z ${PGM_BUILDTYPE} ];
-+then
-+	echo "Name=${PGM_NAME}-${PGM_VERSION}" >> /tmp/${MENU_FILE}
-+else
-+	echo "Name=${PGM_NAME}-${PGM_VERSION}-${PGM_BUILDTYPE}" >> /tmp/${MENU_FILE}
-+fi
-+echo "Icon=${ICON_NAME}" >> /tmp/${MENU_FILE}
-+echo "Comment=Digital Audio Workstation" >> /tmp/${MENU_FILE}
-+echo "Categories=AudioVideo;AudioEditing;Audio;Recorder;" >> /tmp/${MENU_FILE}
-+
-+chmod ugo+rx /tmp/${MENU_FILE}
-+${SUPER} mv /tmp/${MENU_FILE} ${MENU_FILE_PATH}/.
-+
-+# install the Menu, Link, and Icon(s)
-+if [ "T" = ${HAS_XDG} ];
-+then
-+	echo "Adding ${PGM_NAME} to the applications menu"
-+	${SUPER} xdg-icon-resource install --context apps --size 16 ${ICON_PATH}/${PGM_NAME_LOWER}_icon_16px.png ${ICON_NAME}
-+	${SUPER} xdg-icon-resource install --context apps --size 22 ${ICON_PATH}/${PGM_NAME_LOWER}_icon_22px.png ${ICON_NAME}
-+	${SUPER} xdg-icon-resource install --context apps --size 32 ${ICON_PATH}/${PGM_NAME_LOWER}_icon_32px.png ${ICON_NAME}
-+	${SUPER} xdg-icon-resource install --context apps --size 48 ${ICON_PATH}/${PGM_NAME_LOWER}_icon_48px.png ${ICON_NAME}
-+
-+	if [ -e ${ICON_PATH}/${PGM_NAME_LOWER}_icon.svg -a -d /usr/share/icons/hicolor/scalable/apps ]; 
-+	then
-+		${SUPER} cp -f ${ICON_PATH}/${PGM_NAME_LOWER}_icon.svg  /usr/share/icons/hicolor/scalable/apps/${ICON_NAME}.svg
-+	fi
-+
-+	${SUPER} xdg-desktop-menu install ${MENU_FILE_PATH}/${MENU_FILE}
-+	${SUPER} xdg-desktop-menu forceupdate --mode system			# Some systems need an extra kick
-+	
-+	echo ""
-+	echo "Creating a desktop link for ${PGM_NAME}"
-+	cp ${MENU_FILE_PATH}/${MENU_FILE} ~/Desktop/${DESKTOP_LINK_FILE}
-+	chmod ugo+rx ~/Desktop/${DESKTOP_LINK_FILE}
-+else
-+	echo ""
-+	echo "Creating a desktop link for ${PGM_NAME}"
-+	cp ${MENU_FILE_PATH}/${MENU_FILE} ~/Desktop/${DESKTOP_LINK_FILE}
-+	chmod ugo+rx ~/Desktop/${DESKTOP_LINK_FILE}
-+fi
-+
-+echo ""
-+echo "Copying uninstall script to ${INSTALL_DEST_BASE}"
-+echo ""
-+
-+${SUPER} cp -f ${BUNDLE_DIR}/bin/*.uninstall.sh ${INSTALL_DEST_BASE}/.
-+
-+###########################
-+# Check Jack and qjackctl
-+###########################
-+
-+echo ""
-+echo "Checking to see if Jack is installed"
-+echo ""
-+
-+if ! which jackd > /dev/null;
-+then
-+	echo ""
-+	echo "The program Jack is missing from this system. Jack is a required component of $PGM_NAME."
-+	echo ""
-+
-+	ANSWER=$(VaildateYesNoQuestion "Install jack using system software repository?")
-+
-+	if test "y" = $ANSWER;
-+	then
-+		echo "Attempting to install Jack"
-+		SystemInstall "jackd"
-+
-+		if [ $? -ne 0 ];
-+		then
-+			echo ""
-+			read -p "Press ENTER to continue:" BLAH
-+		fi
-+	fi
-+else
-+	echo "Jack OK"
-+fi
-+
-+
-+if ! which qjackctl > /dev/null;
-+then
-+	echo ""
-+	echo "The program QjackCtl is missing from this system."
-+	echo "QjackCtl is an extremely useful tool for any system that runs JACK applications like $PGM_NAME."
-+	echo "We recommend that you install it."
-+	echo ""
-+
-+	ANSWER=$(VaildateYesNoQuestion "Install QjackCtl using system software repository?")
-+
-+	if test "y" = $ANSWER;
-+	then
-+		echo "Attempting to install QjackCtl"
-+		SystemInstall "qjackctl"
-+
-+		if [ $? -ne 0 ];
-+		then
-+			echo ""
-+			read -p "Press ENTER to continue:" BLAH
-+		fi
-+	fi
-+fi
-+
-+
-+########################
-+# Run Sanity Check
-+########################
-+
-+USER_GROUP_ADJUSTED="f"
-+
-+if ! ./${BUNDLE_DIR}/bin/sanityCheck -a > /dev/null;
-+then
-+	echo ""
-+	echo "System failed the quick sanity check... Looking for the cause"
-+
-+	if ! ./${BUNDLE_DIR}/bin/sanityCheck -rt > /dev/null;
-+	then
-+		echo ""
-+		echo "System does not allow realtime for the current user... Looking for a solution"		
-+		
-+		if ./${BUNDLE_DIR}/bin/sanityCheck -hasaudiogroup > /dev/null;
-+		then
-+			if ./${BUNDLE_DIR}/bin/sanityCheck -memberaudiogroup > /dev/null 2>&1;
-+			then
-+				## This is an odd case. We have an audio group and are a member.
-+				echo ""
-+				echo "!!! WARNING !!! - The current user can not execute realtime processes."
-+				echo "This will adversely affect audio latency."
-+				echo "This system has an audio group and the user is a member. If jack was"
-+				echo "just installed, a simple log out/in may fix this."
-+				echo ""
-+				echo "For best results, please correct this on your system."
-+				echo "(Hint: check /etc/security/limits.conf or /etc/security/limits.d/)" 
-+				echo ""
-+				read -p "Press ENTER to continue:" BLAH
-+			else
-+				# Not a member of an audio group. Try to fix it.
-+				
-+				if ./${BUNDLE_DIR}/bin/sanityCheck -hasgroup audio > /dev/null && find /etc/security -type f -name "*.conf" | xargs grep -q "^@audio.*rtprio";
-+				then
-+					# add user to audio group
-+					echo ""
-+					echo "Adding user `whoami` to the audio group."
-+					echo "This should allow you to run realtime tasks. Please re-login for this change to take affect."
-+					echo ""
-+					read -p "Press ENTER to continue:" BLAH
-+
-+					user=`whoami`
-+					if ${SUPER} usermod -a -G audio $user;
-+					then
-+						USER_GROUP_ADJUSTED="t"
-+					else
-+						echo ""
-+						echo "!!! ERROR !!! - Not able to add user to the audio group (usermod failed)!"
-+						echo ""
-+						echo "Please add yourself to the audio group and re-login"
-+						echo ""
-+						read -p "Press ENTER to continue:" BLAH
-+					fi
-+
-+				elif ./${BUNDLE_DIR}/bin/sanityCheck -hasgroup jackuser > /dev/null && find /etc/security -type f -name "*.conf" | xargs grep -q "^@jackuser.*rtprio";
-+				then
-+					# add user to jackuser group
-+					echo ""
-+					echo "Adding user `whoami` to the jackuser group."
-+					echo "This should allow you to run realtime tasks. Please re-login for this change to take affect."
-+					echo ""
-+					read -p "Press ENTER to continue:" BLAH
-+
-+					user=`whoami`
-+					if ${SUPER} usermod -a -G jackuser $user;
-+					then
-+						USER_GROUP_ADJUSTED="t"
-+					else
-+						echo ""
-+						echo "!!! ERROR !!! - Not able to add user to the jackuser group."
-+						echo ""
-+						echo "Please add yourself to the audio group and re-login"
-+						echo ""
-+						read -p "Press ENTER to continue:" BLAH
-+					fi
-+					
-+
-+				fi
-+			fi
-+		else
-+			# No audio group found on this system!
-+			echo ""
-+			echo "!!! WARNING !!! - The system does not seem to have an audio group (audio or jackuser)."
-+			echo ""
-+			echo "We will not attempt to fix this. Please configure your system to allow"
-+			echo "non-root users to execute realtime tasks."
-+			echo ""
-+			read -p "Press ENTER to continue:" BLAH
-+		fi
-+	fi
-+
-+	if ! ./${BUNDLE_DIR}/bin/sanityCheck -freqscaling > /dev/null;
-+	then
-+		echo ""
-+		echo "!!! WARNING !!! - Your system seems to use frequency scaling."
-+		echo "This can have a serious impact on audio latency. You have two choices:"
-+		echo "(1) turn it off, e.g. by chosing the 'performance' governor."
-+		echo "(2) Use the HPET clocksource by passing \"-c h\" to JACK"
-+		echo "(this second option only works on relatively recent computers)"
-+		echo ""
-+		read -p "Press ENTER to continue:" BLAH
-+	fi
-+
-+	if [ "f" = $USER_GROUP_ADJUSTED ];
-+	then
-+		if ! ./${BUNDLE_DIR}/bin/sanityCheck -memlock > /dev/null;
-+		then
-+			echo ""
-+			echo "!!! WARNING !!! - You are not allowed to lock memory."
-+			echo ""
-+			echo "We will not attempt to fix this. Please configure your system to allow"
-+			echo "non-root users to execute lock memory."
-+			echo ""
-+			read -p "Press ENTER to continue:" BLAH
-+		fi
-+	fi
-+fi
-+
-+
-+########################
-+# Install Complete
-+########################
-+
-+echo ""
-+echo "Cleaning up"
-+rm -rf ${BUNDLE_DIR}/
-+
-+echo ""
-+echo "!!! Install Complete !!!"
-+
-+if [ "t" = $USER_GROUP_ADJUSTED ];
-+then
-+	echo "You will need to logout and then login again for all changes to be complete"
-+fi
-+
-+echo ""
-+read -p "Press ENTER to exit installer:" BLAH
-+
-+
-diff --git a/tools/linux_packaging/uninstall.sh.in b/tools/linux_packaging/uninstall.sh.in
-new file mode 100644
-index 0000000..7e86b2b
---- /dev/null
-+++ b/tools/linux_packaging/uninstall.sh.in
-@@ -0,0 +1,130 @@
-+#!/bin/sh
-+
-+######################################
-+#
-+#	Ardour/Mixbus bundle uninstaller
-+#	Todd Naugle
-+#
-+#####################################
-+
-+
-+PGM_NAME="%REPLACE_PGM%"
-+PGM_VENDOR="%REPLACE_VENDOR%"
-+PGM_VERSION="%REPLACE_VERSION%"
-+PGM_BUILD="%REPLACE_BUILD%"
-+PGM_BUILDTYPE="%REPLACE_TYPE%"
-+
-+INSTALL_DEST_BASE=/opt
-+
-+
-+#### Derived Variables ####
-+if [ -z "${PGM_BUILDTYPE}" ]; then
-+	PGM_PATH=${INSTALL_DEST_BASE}/${PGM_NAME}-${PGM_VERSION}_${PGM_BUILD}
-+	ICON_NAME="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}"			#no dash between name and version since dash seperates vendor from program
-+	MENU_FILE="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}.desktop"	#no dash between name and version since dash seperates vendor from program
-+	DESKTOP_LINK_FILE="${PGM_NAME}_${PGM_VERSION}.desktop"
-+else
-+	PGM_PATH=${INSTALL_DEST_BASE}/${PGM_NAME}-${PGM_VERSION}_${PGM_BUILD}-${PGM_BUILDTYPE}
-+	ICON_NAME="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}_${PGM_BUILDTYPE}"			#no dash between name and version since dash seperates vendor from program
-+	MENU_FILE="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}_${PGM_BUILDTYPE}.desktop"	#no dash between name and version since dash seperates vendor from program
-+	DESKTOP_LINK_FILE="${PGM_NAME}_${PGM_VERSION}_${PGM_BUILDTYPE}.desktop"
-+fi
-+
-+MENU_FILE_PATH="${PGM_PATH}/share/${MENU_FILE}"
-+
-+
-+#############################
-+# Check for root privileges
-+#############################
-+
-+SUPER=""
-+
-+if [ "$(id -u)" != "0" ]; then
-+
-+	if ! which sudo > /dev/null;
-+	then
-+		echo ""
-+		echo "!!! ERROR !!!"
-+		echo ""
-+		echo "The uninstaller requires root privileges. It is currently not"
-+		echo "running as root AND the program sudo is missing from this system."
-+		echo ""
-+		echo "Please correct this by running the uninstaller as root or"
-+		echo "installing and configuring sudo."
-+		echo ""
-+		read -p "Press ENTER to exit uninstaller:" BLAH
-+		exit 1
-+	fi
-+
-+	if ! sudo date;
-+	then
-+		echo ""
-+		echo "!!! ERROR !!!"
-+		echo ""
-+		echo "Either you don't know the root password or the user is not allowed to sudo"
-+		echo "Please correct this and run the uninstaller again"
-+		echo "(hint: use visudo to edit sudoers file or run the installer as root)"
-+		echo ""
-+		read -p "Press ENTER to exit uninstaller:" BLAH
-+		exit 1
-+	fi
-+	SUPER="sudo"
-+fi
-+
-+#######################
-+# Check for xdg utils
-+#######################
-+HAS_XDG="T"
-+
-+XDG_MENU_VER=$(xdg-desktop-menu --version 2> /dev/null)
-+if [ -z "$XDG_MENU_VER" ];
-+then
-+	echo "System does not have xdg-desktop-menu installed"
-+	HAS_XDG="F"
-+fi
-+
-+XDG_ICON_VER=$(xdg-icon-resource --version 2> /dev/null)
-+if [ -z "$XDG_ICON_VER" ];
-+then
-+	echo "System does not have xdg-icon-resource installed"
-+	HAS_XDG="F"
-+fi
-+
-+
-+#############
-+# Uninstall
-+#############
-+
-+if [ -d ${PGM_PATH} ];
-+then
-+	echo ""
-+	echo "Removing existing ${PGM_NAME} installation at ${PGM_PATH}"
-+	echo ""
-+
-+	if [ "T" = ${HAS_XDG} ];
-+	then
-+		${SUPER} xdg-desktop-menu uninstall ${MENU_FILE_PATH}
-+		${SUPER} xdg-icon-resource uninstall --size 16 ${ICON_NAME}
-+		${SUPER} xdg-icon-resource uninstall --size 22 ${ICON_NAME}
-+		${SUPER} xdg-icon-resource uninstall --size 32 ${ICON_NAME}
-+		${SUPER} xdg-icon-resource uninstall --size 48 ${ICON_NAME}
-+
-+		if [ -e /usr/share/icons/hicolor/scalable/apps/${ICON_NAME}.svg ]; 
-+		then
-+			${SUPER} rm -f /usr/share/icons/hicolor/scalable/apps/${ICON_NAME}.svg
-+		fi
-+	fi
-+
-+	if [ -e ~/Desktop/${DESKTOP_LINK_FILE} ];
-+	then
-+		${SUPER} rm -f ~/Desktop/${DESKTOP_LINK_FILE}
-+	fi
-+
-+	# delete the old package
-+	${SUPER} rm -rf ${PGM_PATH}
-+	${SUPER} rm -f $0
-+else
-+	echo ""
-+	echo "!!! FAILURE !!! - install path ${PGM_PATH} does not exist."
-+	echo ""
-+fi
-diff --git a/tools/sanity_check/SConscript b/tools/sanity_check/SConscript
-new file mode 100644
-index 0000000..7064141
---- /dev/null
-+++ b/tools/sanity_check/SConscript
-@@ -0,0 +1,12 @@
-+# -*- python -*-
-+
-+import os
-+import os.path
-+import glob
-+
-+Import('env')
-+sanitycheck = env.Clone()
-+sc = sanitycheck.Program('sanityCheck', ['main.cpp', 'systemtest.cpp'])
-+
-+Default(sc)
-+
-diff --git a/tools/sanity_check/main.cpp b/tools/sanity_check/main.cpp
-new file mode 100644
-index 0000000..c1886b2
---- /dev/null
-+++ b/tools/sanity_check/main.cpp
-@@ -0,0 +1,359 @@
-+/*
-+ * 
-+ *   program:  sanityCheck 
-+ *   file:     main.c
-+ *   author:   Todd Naugle
-+ *   date:     11/17/2010
-+ * 
-+ *   Desc:  Command line version of the sanity check functions found in jack
-+*/ 
-+
-+#include <algorithm>
-+#include <stdio.h>
-+#include <string>
-+#include <vector>
-+
-+#include "systemtest.h"
-+
-+
-+using namespace std;
-+
-+typedef int (*testfuncPtr) ();
-+typedef int (*testfuncOpPtr) (string);
-+
-+typedef struct
-+{
-+	string			switchText;			// ie -option
-+	string			swOptionText;       // option arguments for just this swtich.
-+	string			descriptionText;	// Help Text on what this does
-+	string			failureText;		// What to say when this test fails
-+	bool			hasOption;			// Set true if this switch has option paramters
-+	testfuncPtr		functionPtr;		// Function to call
-+	testfuncOpPtr	opFunctionPtr;		// Function with option string to call
-+	string			optionArg;			// Storage used to hold any options passed in by the user
-+} testRecord;
-+
-+static vector<testRecord>	gTestSet;
-+	
-+static vector<string>		gValidSwitchList;
-+static vector<string>		gSwitchDescriptionList;
-+
-+static vector<string>		gSwitchesReceived;
-+
-+int
-+ExecuteAll()
-+{
-+	bool OK = true;
-+
-+	OK &= system_user_can_rtprio();
-+
-+	if (system_has_frequencyscaling()) {
-+		OK &= !system_uses_frequencyscaling();
-+	}
-+
-+	OK &= !(system_memlock_amount() == 0);
-+	
-+	return OK;
-+}
-+
-+int
-+HasGroup(string name)
-+{
-+	return system_has_group(name.c_str());
-+}
-+
-+int
-+IsMemberOfGroup(string name)
-+{
-+	return system_user_in_group(name.c_str());
-+}
-+
-+int
-+CheckFreqScaling()
-+{
-+	bool OK = true;
-+
-+	if (system_has_frequencyscaling()) {
-+		OK &= !system_uses_frequencyscaling();
-+	}
-+
-+	return OK;
-+}
-+
-+int
-+CheckMemoryLocking()
-+{
-+	return !(system_memlock_amount() == 0);
-+}
-+
-+int
-+PrintUsage()
-+{
-+	printf("\n");
-+	printf("  sanityCheck - A program to verify proper system settings for use with audio applications (Ardour/Jack/Mixbus).\n");
-+	printf("\n");
-+	printf("  Usage:  sanityCheck [OPTIONS]\n");
-+	printf("\n");
-+	printf("  Options are as follows:\n");
-+	printf("\n");
-+	printf("\n");
-+	
-+	vector<testRecord>::iterator		itr;
-+	
-+	for (itr = gTestSet.begin(); itr != gTestSet.end(); ++itr) {
-+		printf("%20s %s :\t%s\n", (*itr).switchText.c_str(), (*itr).swOptionText.c_str(), (*itr).descriptionText.c_str());
-+	}
-+
-+	printf("\n");
-+	
-+	return true;
-+}
-+
-+void
-+DefineSwitches()
-+{
-+	testRecord rec;
-+	
-+	// Global switches
-+	rec.switchText = "-a";
-+	rec.swOptionText = "";
-+	rec.descriptionText = "Checks for a working RT system. Same as -rt -freqscaling -memlock";
-+	rec.failureText = "";
-+	rec.hasOption = false;
-+	rec.functionPtr = &ExecuteAll;
-+	rec.optionArg = "";
-+	gTestSet.push_back(rec);
-+
-+	rec.switchText = "-h";
-+	rec.swOptionText = "";
-+	rec.descriptionText = "Print usage";
-+	rec.failureText = "";
-+	rec.hasOption = false;
-+	rec.functionPtr = &PrintUsage;
-+	rec.optionArg = "";
-+	gTestSet.push_back(rec);
-+
-+	// Switches for various tests that can be performed.
-+	rec.switchText = "-rt";
-+	rec.swOptionText = "";
-+	rec.descriptionText = "Verfiy that the user can run tasks with realtime priority";
-+	rec.failureText = "";
-+	rec.hasOption = false;
-+	rec.functionPtr = &system_user_can_rtprio;
-+	rec.optionArg = "";
-+	gTestSet.push_back(rec);
-+
-+	rec.switchText = "-hasrtlimits";
-+	rec.swOptionText = "";
-+	rec.descriptionText = "Verfiy the system has a limits.conf and the audio group can use realtime";
-+	rec.failureText = "";
-+	rec.hasOption = false;
-+	rec.functionPtr = &system_has_rtprio_limits_conf;
-+	rec.optionArg = "";
-+	gTestSet.push_back(rec);
-+
-+	rec.switchText = "-hasgroup";
-+	rec.swOptionText = "<groupname>";
-+	rec.descriptionText = "Verfiy that the system has a group named <groupname>";
-+	rec.failureText = "";
-+	rec.hasOption = true;
-+	rec.opFunctionPtr = &HasGroup;
-+	rec.optionArg = "";
-+	gTestSet.push_back(rec);
-+
-+	rec.switchText = "-hasaudiogroup";
-+	rec.swOptionText = "";
-+	rec.descriptionText = "Verfiy that the system has an audio group (audio or jackuser) defined";
-+	rec.failureText = "";
-+	rec.hasOption = false;
-+	rec.functionPtr = &system_has_audiogroup;
-+	rec.optionArg = "";
-+	gTestSet.push_back(rec);
-+
-+	rec.switchText = "-memberofgroup";
-+	rec.swOptionText = "<groupname>";
-+	rec.descriptionText = "Verfiy that the user is a member of the group named <groupname>";
-+	rec.failureText = "";
-+	rec.hasOption = true;
-+	rec.opFunctionPtr = &IsMemberOfGroup;
-+	rec.optionArg = "";
-+	gTestSet.push_back(rec);
-+
-+	rec.switchText = "-memberaudiogroup";
-+	rec.swOptionText = "";
-+	rec.descriptionText = "Verfiy that the user is a member of the audio group (audio or jackuser)";
-+	rec.failureText = "";
-+	rec.hasOption = false;
-+	rec.functionPtr = &system_user_in_audiogroup;
-+	rec.optionArg = "";
-+	gTestSet.push_back(rec);
-+
-+	rec.switchText = "-freqscaling";
-+	rec.swOptionText = "";
-+	rec.descriptionText = "Check to see if frequency scaling is being used by the CPU";
-+	rec.failureText = "";
-+	rec.hasOption = false;
-+	rec.functionPtr = &CheckFreqScaling;
-+	rec.optionArg = "";
-+	gTestSet.push_back(rec);
-+
-+	rec.switchText = "-memlock";
-+	rec.swOptionText = "";
-+	rec.descriptionText = "Check to see if the user is able to lock memory";
-+	rec.failureText = "";
-+	rec.hasOption = false;
-+	rec.functionPtr = &CheckMemoryLocking;
-+	rec.optionArg = "";
-+	gTestSet.push_back(rec);
-+
-+}
-+
-+bool
-+ParseSwitches(
-+	int		argc,
-+	char	**argv)
-+{
-+	string	tmp;
-+	vector<testRecord>::iterator	itr;
-+	bool	OK = true;
-+	int	i;
-+	
-+	if (argc == 1) {
-+		gSwitchesReceived.push_back("-a");
-+	}
-+	else {
-+		for (i = 1; i < argc && OK == true; i++) {
-+			tmp = argv[i];
-+
-+			for (itr = gTestSet.begin(); itr != gTestSet.end(); ++itr) {
-+				if (tmp == (*itr).switchText) {
-+					if ((*itr).hasOption == true) {
-+						if (++i < argc) {
-+							string	op = argv[i];
-+							if (op[0] == '-') {
-+								// reqiured option for this switch is missing
-+								--i;
-+								OK = false;
-+								break;
-+							}
-+							(*itr).optionArg = op;
-+							break;
-+						}
-+						else {
-+							// reqiured option for this switch is missing
-+							--i;
-+							OK = false;
-+							break;
-+						}
-+					}
-+					break;
-+				}
-+			}
-+			
-+			if (OK && itr != gTestSet.end()) {
-+				// Known option switch found
-+				gSwitchesReceived.push_back(tmp);
-+			}
-+			else {
-+				// Unknown option
-+				OK = false;
-+			}
-+		}
-+	}
-+
-+	if (OK) {
-+		// All switches are at least valid, now check to make sure they are all valid to 
-+		// be used together.
-+		
-+		if (gSwitchesReceived.size() > 1) {
-+			// make sure help is not mixed with other options
-+			vector<string>::iterator	swItr;
-+			tmp = "-h";
-+
-+			swItr = find(gSwitchesReceived.begin(), gSwitchesReceived.end(), tmp);
-+
-+			if (swItr != gSwitchesReceived.end()) {
-+				gSwitchesReceived.clear();
-+				gSwitchesReceived.push_back("-h");
-+			}
-+
-+			// make sure -a is only used by itself
-+			tmp = "-a";
-+			swItr = find(gSwitchesReceived.begin(), gSwitchesReceived.end(), tmp);
-+
-+			if (swItr != gSwitchesReceived.end()) {
-+				gSwitchesReceived.clear();
-+				gSwitchesReceived.push_back("-a");
-+			}
-+		}
-+
-+		return true;
-+	}
-+	else {
-+		fprintf(stderr, "\n");
-+		fprintf(stderr, "ERROR - Invalid Option: %s\n", (const char *) argv[--i]); 
-+		fprintf(stderr, "Check syntax\n");
-+		PrintUsage();
-+		return false;
-+	}
-+}
-+
-+bool
-+Execute()
-+{
-+	bool OK = true;
-+	vector<string>::iterator	itr;
-+	vector<testRecord>::iterator	testItr;
-+	
-+	for (itr = gSwitchesReceived.begin(); itr != gSwitchesReceived.end(); ++itr) {
-+		for (testItr = gTestSet.begin(); testItr != gTestSet.end(); ++testItr) {
-+			if ((*itr) == (*testItr).switchText) {
-+				break;
-+			}
-+		}
-+		
-+		bool result;
-+		if ((*testItr).hasOption) {
-+			result = ((*testItr).opFunctionPtr((*testItr).optionArg) != 0);
-+		}
-+		else {
-+			result = ((*testItr).functionPtr() != 0);
-+		}
-+
-+		if (result == 0) {
-+			// Check for a Failure message and print it if found.
-+			if (!(*testItr).failureText.empty()) {
-+				printf("\n%s\n", (*testItr).failureText.c_str());
-+			}
-+		}
-+
-+		OK &= result;
-+	}
-+	
-+	return OK;
-+}
-+
-+int
-+main(
-+	int		 argc,
-+	char 	**argv)
-+{
-+	int status = 0;
-+	
-+	DefineSwitches();
-+
-+	if (ParseSwitches(argc, argv)) {
-+		if (Execute() == false) {
-+			printf("\nSanity Check Failed!\n\n");
-+			status = -1;
-+		}
-+		else {
-+			printf("\nSanity Check OK!\n\n");
-+		}
-+	}
-+	else {
-+		status = -1;
-+	}
-+
-+	return status;
-+}
-diff --git a/tools/sanity_check/systemtest.cpp b/tools/sanity_check/systemtest.cpp
-new file mode 100644
-index 0000000..4801ac2
---- /dev/null
-+++ b/tools/sanity_check/systemtest.cpp
-@@ -0,0 +1,333 @@
-+/**
-+ * This program is free software; you can redistribute it and/or modify
-+ * it under the terms of the GNU General Public License as published by
-+ * the Free Software Foundation; either version 2 of the License, or
-+ * (at your option) any later version.
-+ *
-+ * This program is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU General Public License for more details.
-+ *
-+ * You should have received a copy of the GNU General Public License
-+ * along with this program; if not, write to the Free Software
-+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-+ *
-+ * Set of functions to gather system information for the jack setup wizard.
-+ * 
-+ * TODO: Test for rt prio availability
-+ *
-+ * @author Florian Faber, faber at faberman.de
-+ *
-+ **/
-+
-+/** maximum number of groups a user can be a member of **/
-+#define MAX_GROUPS 100
-+
-+#include <fcntl.h>
-+
-+#include <stdlib.h>
-+#include <sys/types.h>
-+#include <unistd.h>
-+#include <grp.h>
-+
-+#include <sched.h>
-+#include <string.h>
-+
-+#include <sys/time.h>
-+#include <sys/resource.h>
-+
-+#include <stdio.h>
-+#include <errno.h>
-+
-+#include "systemtest.h"
-+
-+/**
-+ * This function checks for the existence of known frequency scaling mechanisms 
-+ * in this system by testing for the availability of scaling governors/
-+ *
-+ * @returns 0 if the system has no frequency scaling capabilities non-0 otherwise.
-+ **/
-+int system_has_frequencyscaling() {
-+  int fd;
-+
-+  fd = open("/sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors", O_RDONLY);
-+
-+  if (-1==fd) {
-+    return 0;
-+  }
-+
-+  (void) close(fd);
-+
-+  return 1;
-+}
-+
-+
-+static int read_string(char* filename, char* buf, size_t buflen) {
-+  int fd;
-+  ssize_t r=-1;
-+
-+  memset (buf, 0, buflen);
-+
-+  fd = open (filename, O_RDONLY);
-+  if (-1<fd) {
-+    r = read (fd, buf, buflen-1);
-+    (void) close(fd);
-+    
-+    if (-1==r) {
-+      fprintf(stderr, "Error while reading \"%s\": %s\n", filename, strerror(errno));
-+      exit(EXIT_FAILURE);
-+    }
-+  }
-+  
-+  return (int) r;
-+}
-+
-+
-+static int read_int(char* filename, int* value) {
-+  char buf[20];
-+
-+  if (0<read_string(filename, buf, 20)) {
-+		return (1==sscanf(buf, "%d", value));
-+  }
-+
-+  return 0;
-+}
-+
-+
-+/**
-+ * This function determines wether any CPU core uses a variable clock speed if frequency 
-+ * scaling is available. If the governor for all cores is either "powersave" or
-+ * "performance", the CPU frequency can be assumed to be static. This is also the case
-+ * if scaling_min_freq and scaling_max_freq are set to the same value.
-+ *
-+ * @returns 0 if system doesn't use frequency scaling at the moment, non-0 otherwise
-+ **/
-+int system_uses_frequencyscaling() {
-+  int cpu=0, done=0, min, max;
-+  char filename[256], buf[256];
-+
-+  while (!done) {
-+          (void) snprintf(filename, 256, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_governor", cpu);
-+          if (0<read_string(filename, buf, 256)) {
-+                  if ((0!=strncmp("performance", buf, 11)) && 
-+                      (0!=strncmp("powersafe", buf, 9))) {
-+                          // So it's neither the "performance" nor the "powersafe" governor
-+                          (void) snprintf(filename, 256, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_min_freq", cpu);
-+                          if (read_int(filename, &min)) {
-+                                  (void) snprintf(filename, 256, "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_max_freq", cpu);
-+                                  if (read_int(filename, &max)) {
-+                                          if (min!=max) {
-+                                                  // wrong governor AND different frequency limits -> scaling
-+                                                  return 1;
-+                                          }
-+                                  } 
-+                          }
-+                  }
-+          } else {
-+                  // couldn't open file -> no more cores
-+                  done = 1;
-+          }
-+          cpu++;
-+  }
-+  
-+  // couldn't find anything that points to scaling
-+  return 0;
-+}
-+
-+
-+static gid_t get_group_by_name(const char* name) {
-+  struct group* grp;
-+	gid_t res = 0;
-+
-+  while ((0==res) && (NULL != (grp = getgrent()))) {
-+    if (0==strcmp(name, grp->gr_name)) {
-+      res = grp->gr_gid;
-+    }
-+  }
-+
-+	endgrent();
-+
-+  return res;
-+}
-+
-+/**
-+ * Tests wether the owner of this process is in the group 'name'.
-+ *
-+ * @returns 0 if the owner of this process is not in the group, non-0 otherwise
-+ **/
-+int system_user_in_group(const char *name) {
-+  gid_t* list = (gid_t*) malloc(MAX_GROUPS * sizeof(gid_t));
-+  int num_groups, i=0, found=0;
-+	unsigned int gid;
-+
-+  if (NULL==list) {
-+    perror("Cannot allocate group list structure");
-+    exit(EXIT_FAILURE);
-+  }
-+
-+  gid = get_group_by_name(name);
-+  if (0==gid) {
-+    fprintf(stderr, "No %s group found\n", name);
-+    return 0;
-+  }
-+  
-+  num_groups = getgroups(MAX_GROUPS, list);
-+  
-+  while (i<num_groups) {
-+    if (list[i]==gid) {
-+      found = 1;
-+      i = num_groups;
-+    }
-+    
-+    i++;
-+  }
-+  
-+  free(list);
-+
-+  return found;
-+}
-+
-+
-+/***
-+ * Checks for a definition in /etc/security/limits.conf that looks
-+ * as if it allows RT scheduling priority.
-+ *
-+ * @returns 1 if there appears to be such a line
-+ **/
-+int system_has_rtprio_limits_conf ()
-+{
-+	const char* limits = "/etc/security/limits.conf";
-+	char cmd[100];
-+
-+	snprintf (cmd, sizeof (cmd), "grep -q 'rtprio *[0-9][0-9]*' %s", limits);
-+	if (system (cmd) == 0) {
-+		return 1;
-+	}
-+	return 0;
-+}
-+
-+
-+/**
-+ * Checks for the existence of the 'audio' group on this system
-+ *
-+ * @returns 0 if there is no 'audio' group, the group id otherwise
-+ **/
-+int system_has_audiogroup() {
-+	return get_group_by_name("audio") || get_group_by_name ("jackuser");
-+}
-+
-+
-+/**
-+ * Checks for the existence of 'groupname' on this system
-+ *
-+ * @returns 0 if there is no group, the group id otherwise
-+ **/
-+int system_has_group(const char * name) {
-+	return get_group_by_name(name);
-+}
-+
-+
-+/**
-+ * Tests wether the owner of this process is in the 'audio' group.
-+ *
-+ * @returns 0 if the owner of this process is not in the audio group, non-0 otherwise
-+ **/
-+int system_user_in_audiogroup() {
-+	return system_user_in_group("audio") || system_user_in_group("jackuser");
-+}
-+
-+
-+/**
-+ * Determines wether the owner of this process can enable rt priority.
-+ *
-+ * @returns 0 if this process can not be switched to rt prio, non-0 otherwise
-+ **/
-+int system_user_can_rtprio() {
-+  int min_prio;
-+  struct sched_param schparam;
-+
-+  memset(&schparam, 0, sizeof(struct sched_param));
-+
-+  if (-1 == (min_prio = sched_get_priority_min(SCHED_FIFO))) {
-+    perror("sched_get_priority");
-+    exit(EXIT_FAILURE);
-+  }
-+  schparam.sched_priority = min_prio;  
-+
-+  if (0 == sched_setscheduler(0, SCHED_FIFO, &schparam)) {
-+    // TODO: restore previous state
-+    schparam.sched_priority = 0;
-+    if (0 != sched_setscheduler(0, SCHED_OTHER, &schparam)) {
-+      perror("sched_setscheduler");
-+      exit(EXIT_FAILURE);
-+    }
-+    return 1;
-+  }  
-+
-+  return 0;
-+}
-+
-+
-+long long unsigned int system_memlock_amount() {
-+	struct rlimit limits;
-+
-+	if (-1==getrlimit(RLIMIT_MEMLOCK, &limits)) {
-+		perror("getrlimit on RLIMIT_MEMLOCK");
-+		exit(EXIT_FAILURE);
-+	}
-+
-+	return limits.rlim_max;
-+}
-+
-+
-+/**
-+ * Checks wether the memlock limit is unlimited
-+ *
-+ * @returns - 0 if the memlock limit is limited, non-0 otherwise
-+ **/
-+int system_memlock_is_unlimited() {
-+	return ((RLIM_INFINITY==system_memlock_amount())?1:0);
-+}
-+
-+
-+long long unsigned int system_available_physical_mem() {
-+	char buf[256];
-+	long long unsigned int res = 0;
-+
-+	if (0<read_string((char*)"/proc/meminfo", buf, sizeof (buf))) {
-+		if (strncmp (buf, "MemTotal:", 9) == 0) {
-+			if (sscanf (buf, "%*s %llu", &res) != 1) {
-+				perror ("parse error in /proc/meminfo");
-+			} 
-+		}
-+	} else {
-+		perror("read from /proc/meminfo");
-+	}
-+
-+	return res*1024;
-+}
-+
-+
-+/**
-+ * Gets the version of the currently running kernel. The string
-+ * returned has to be freed by the caller.
-+ *
-+ * @returns String with the full version of the kernel
-+ **/
-+char* system_kernel_version() {
-+  return NULL;
-+}
-+
-+
-+
-+char* system_get_username() {
-+  char* res = NULL;
-+  char* name = NULL;
-+
-+  if ((name = getlogin())) {
-+    res = strdup(name);
-+  }
-+
-+  return res;
-+}
-diff --git a/tools/sanity_check/systemtest.h b/tools/sanity_check/systemtest.h
-new file mode 100644
-index 0000000..f9eb920
---- /dev/null
-+++ b/tools/sanity_check/systemtest.h
-@@ -0,0 +1,109 @@
-+#ifndef __systemtest_h__
-+#define __systemtest_h__
-+
-+/**
-+ * GPL, yabbadabba
-+ *
-+ * Set of functions to gather system information for the jack setup wizard.
-+ * 
-+ * @author Florian Faber, faber at faberman.de
-+ * 
-+ * @version 0.1 (2009-01-15) [FF]
-+ *              - initial version
-+ *
-+ **/
-+
-+
-+/**
-+ * This function checks for the existence of known frequency scaling mechanisms 
-+ * in this system.
-+ *
-+ * @returns 0 if the system has no frequency scaling capabilities non-0 otherwise.
-+ **/
-+int system_has_frequencyscaling();
-+
-+
-+/**
-+ * This function determines wether the CPU has a variable clock speed if frequency 
-+ * scaling is available. 
-+ *
-+ * @returns 0 if system doesn't use frequency scaling at the moment, non-0 otherwise
-+ **/
-+int system_uses_frequencyscaling();
-+
-+/**
-+ * Tests wether the owner of this process is in the group 'name'.
-+ *
-+ * @returns 0 if the owner of this process is not in the group, non-0 otherwise
-+ **/
-+int system_user_in_group(const char *name);
-+
-+/***
-+ * Checks for a definition in /etc/security/limits.conf that looks
-+ * as if it allows RT scheduling priority.
-+ *
-+ * @returns 1 if there appears to be such a line
-+ **/
-+int system_has_rtprio_limits_conf ();
-+
-+/**
-+ * Checks for the existence of the 'audio' group on this system
-+ *
-+ * @returns 0 is there is no 'audio' group, non-0 otherwise
-+ **/
-+int system_has_audiogroup();
-+
-+/**
-+ * Checks for the existence of a group named 'name' on this system
-+ *
-+ * @returns 0 if not found, non-0 otherwise
-+ **/
-+int system_has_group(const char * name);
-+
-+/**
-+ * Tests wether the owner of this process is in the 'audio' group.
-+ *
-+ * @returns 0 if the owner of this process is not in the audio group, non-0 otherwise
-+ **/
-+int system_user_in_audiogroup();
-+
-+
-+/**
-+ * Determines wether the owner of this process can enable rt priority.
-+ *
-+ * @returns 0 if this process can not be switched to rt prio, non-0 otherwise
-+ **/
-+int system_user_can_rtprio();
-+
-+
-+long long unsigned int system_memlock_amount();
-+
-+
-+/**
-+ * Checks wether the memlock limit is unlimited
-+ *
-+ * @returns 0 if the memlock limit is limited, non-0 otherwise
-+ **/
-+int system_memlock_is_unlimited();
-+
-+
-+long long unsigned int system_available_physical_mem();
-+
-+
-+/**
-+ * Gets the version of the currently running kernel
-+ *
-+ * @returns String with the full version of the kernel
-+ **/
-+char* system_kernel_version();
-+
-+
-+/**
-+ * Returns the username. The caller is in charge of disposal of
-+ * the returned name.
-+ *
-+ * @returns Pointer to a username or NULL
-+ **/
-+char* system_get_username();
-+
-+#endif /* __jack_systemtest_h__ */

-- 
ardour Debian packaging



More information about the pkg-multimedia-commits mailing list