[SCM] ardour/master: Update VCS patch to r9505

adiknoth-guest at users.alioth.debian.org adiknoth-guest at users.alioth.debian.org
Wed May 18 14:02:50 UTC 2011


The following commit has been merged in the master branch:
commit b18c69cbccb99181862cb7bd841561e5886f51c9
Author: Adrian Knoth <adi at drcomp.erfurt.thur.de>
Date:   Mon May 16 16:25:55 2011 +0200

    Update VCS patch to r9505

diff --git a/debian/patches/000_sync_vcs.patch b/debian/patches/000_sync_vcs.patch
index e1b11ae..640e1cd 100644
--- a/debian/patches/000_sync_vcs.patch
+++ b/debian/patches/000_sync_vcs.patch
@@ -1,7 +1,176 @@
 From: Adrian Knoth <adi at drcomp.erfurt.thur.de>
-Description: Sync with upstream VCS revision 8077
+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 @@
@@ -16,9 +185,144 @@ Forwarded: Not-needed
    <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 @@
+@@ -11,9 +11,9 @@ else
      echo USING OLD CLEARLOOKS
      export GTK_PATH=~/.ardour2:libs/clearlooks-older
  fi
@@ -30,6 +334,20 @@ Forwarded: Not-needed
  
  # 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 @@
@@ -43,6 +361,8 @@ Forwarded: Not-needed
  # 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 @@
@@ -53,7 +373,7 @@ Forwarded: Not-needed
  
  #include <pbd/error.h>
  #include <pbd/basename.h>
-@@ -643,6 +644,11 @@
+@@ -643,6 +644,11 @@ Please consider the possibilities, and perhaps (re)start JACK."));
  void
  ARDOUR_UI::startup ()
  {
@@ -65,7 +385,7 @@ Forwarded: Not-needed
  	string name, path;
  	
  	new_session_dialog = new NewSessionDialog();
-@@ -653,7 +659,9 @@
+@@ -653,7 +659,9 @@ ARDOUR_UI::startup ()
  	if (audio_setup) {
  		new_session_dialog->engine_control.set_state (*audio_setup);
  	}
@@ -76,7 +396,7 @@ Forwarded: Not-needed
  	if (!get_session_parameters (backend_audio_is_running, ARDOUR_COMMAND_LINE::new_session)) {
  		return;
  	}
-@@ -2347,6 +2355,7 @@
+@@ -2347,6 +2355,7 @@ void
  ARDOUR_UI::idle_load (const Glib::ustring& path)
  {
  	if (session) {
@@ -84,7 +404,7 @@ Forwarded: Not-needed
  		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 @@
+@@ -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));
  		}
@@ -99,9 +419,11 @@ Forwarded: Not-needed
  			/* 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 @@
+@@ -891,9 +891,6 @@ ARDOUR_UI::use_menubar_as_top_menubar ()
  	}
  
  	app->set_menu_bar (*menu_bar);
@@ -111,28 +433,169 @@ Forwarded: Not-needed
  }
  
  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 @@
+@@ -378,6 +378,8 @@ AudioStreamView::redisplay_diskstream ()
  	list<RegionView *>::iterator i, tmp;
  	list<CrossfadeView*>::iterator xi, tmpx;
  
-+        cerr << "REDISPLAY diskstream\n";
++//        cerr << "REDISPLAY diskstream\n";
 +
  	for (i = region_views.begin(); i != region_views.end(); ++i) {
  		(*i)->set_valid (false);
  	}
-@@ -424,6 +426,7 @@
+@@ -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;
++//                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 @@
+@@ -1246,12 +1246,12 @@ gnome_canvas_waveview_render (GnomeCanvasItem *item,
  		max = waveview->cache->data[cache_index].max;
  		min = waveview->cache->data[cache_index].min;
  		
@@ -147,9 +610,74 @@ Forwarded: Not-needed
  			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 @@
+@@ -164,7 +164,9 @@ Editor::external_audio_dialog ()
  		}
  
  		SrcQuality quality = sfbrowser->get_src_quality();
@@ -159,7 +687,7 @@ Forwarded: Not-needed
  
  		if (sfbrowser->copy_files_btn.get_active()) {
  			do_import (paths, chns, mode, quality, where);
-@@ -289,6 +291,7 @@
+@@ -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;
@@ -167,7 +695,7 @@ Forwarded: Not-needed
  
  	if (interthread_progress_window == 0) {
  		build_interthread_progress_window ();
-@@ -339,6 +342,11 @@
+@@ -339,6 +342,11 @@ Editor::do_import (vector<ustring> paths, ImportDisposition chns, ImportMode mod
  				/* NOTREACHED*/
  			}
  
@@ -179,7 +707,7 @@ Forwarded: Not-needed
  
  			switch (chns) {
  			case Editing::ImportDistinctFiles:
-@@ -682,14 +690,6 @@
+@@ -682,14 +690,6 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64
  	
  	use_timestamp = (pos == -1);
  
@@ -194,7 +722,7 @@ Forwarded: Not-needed
  	if (target_regions == 1) {
  
  		/* take all the sources we have and package them up as a region */
-@@ -699,8 +699,8 @@
+@@ -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)));
  							   
@@ -205,7 +733,7 @@ Forwarded: Not-needed
  		}
  		
  		regions.push_back (ar);
-@@ -750,16 +750,57 @@
+@@ -750,16 +750,57 @@ Editor::add_sources (vector<Glib::ustring> paths, SourceList& sources, nframes64
  	}
  
  	int n = 0;
@@ -267,9 +795,11 @@ Forwarded: Not-needed
  	}
  
  	/* 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 @@
+@@ -107,13 +107,8 @@ Editor::initialize_canvas ()
  	track_canvas->set_center_scroll_region (false);
  	track_canvas->set_dither (Gdk::RGB_DITHER_NONE);
  
@@ -285,7 +815,7 @@ Forwarded: Not-needed
  
  	/* stuff for the verbose canvas cursor */
  
-@@ -144,21 +139,21 @@
+@@ -144,21 +139,21 @@ Editor::initialize_canvas ()
  
  #ifdef GTKOSX
  	/*XXX please don't laugh. this actually improves canvas performance on osx */
@@ -311,7 +841,7 @@ Forwarded: Not-needed
  	range_marker_drag_rect->hide ();
  
  	_trackview_group = new ArdourCanvas::Group (*_master_group);
-@@ -166,60 +161,60 @@
+@@ -166,60 +161,60 @@ Editor::initialize_canvas ()
  
  	meter_bar_group = new ArdourCanvas::Group (*track_canvas->root ());
  	if (Profile->get_sae()) {
@@ -384,7 +914,7 @@ Forwarded: Not-needed
  		cd_marker_bar->property_outline_pixels() = 0;
  	}
   	cd_marker_bar->property_outline_what() = (0x1 | 0x8);
-@@ -235,7 +230,7 @@
+@@ -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));
@@ -393,7 +923,7 @@ Forwarded: Not-needed
  
  	marker_drag_line = new ArdourCanvas::Line (*timebar_group);
  	marker_drag_line->property_width_pixels() = 1;
-@@ -258,14 +253,14 @@
+@@ -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;
@@ -410,7 +940,7 @@ Forwarded: Not-needed
  	transport_punchout_line->hide();
  	
  	// used to show zoom mode active zooming
-@@ -382,24 +377,20 @@
+@@ -382,24 +377,20 @@ Editor::track_canvas_size_allocated ()
  void
  Editor::controls_layout_size_request (Requisition* req)
  {
@@ -440,22 +970,11 @@ Forwarded: Not-needed
  
  	if ((req->width != width) || (req->height != height)) {
  		changed = true;
---- a/gtk2_ardour/editor.h
-+++ b/gtk2_ardour/editor.h
-@@ -330,10 +330,6 @@
- 	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_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 @@
+@@ -3996,8 +3996,6 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
  		drag_info.x_constrained = !drag_info.x_constrained;
  	}
  
@@ -464,7 +983,7 @@ Forwarded: Not-needed
  	if (drag_info.copy) {
  		if (drag_info.x_constrained) {
  			op_string = _("fixed time region copy");
-@@ -4037,8 +4035,6 @@
+@@ -4037,8 +4035,6 @@ Editor::region_drag_finished_callback (ArdourCanvas::Item* item, GdkEvent* event
  			continue;
  		}
                  
@@ -473,7 +992,7 @@ Forwarded: Not-needed
  		if (changed_position && !drag_info.x_constrained && (mouse_mode != MouseRange)) {
  			where = rv->region()->position() - drag_delta;
  		} else {
-@@ -4074,8 +4070,6 @@
+@@ -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));
  			}
  
@@ -482,7 +1001,7 @@ Forwarded: Not-needed
  			to_playlist->add_region (new_region, where);
  
  			c.disconnect ();
-@@ -4409,8 +4403,6 @@
+@@ -4409,8 +4403,6 @@ Editor::start_selection_grab (ArdourCanvas::Item* item, GdkEvent* event)
  		return;
  	}
  
@@ -491,9 +1010,71 @@ Forwarded: Not-needed
  	/* 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 @@
+@@ -611,8 +611,8 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
  			*/
  			
  			
@@ -504,7 +1085,7 @@ Forwarded: Not-needed
  			
  			for (RegionSelection::iterator i = selection->regions.begin(); i != selection->regions.end(); ++i) {
  				if ((*i)->region()->position() < first_frame) {
-@@ -639,9 +639,9 @@
+@@ -639,9 +639,9 @@ Editor::set_selected_regionview_from_click (bool press, Selection::Operation op,
  			   the this one and any selected ones.
  			*/
  
@@ -516,6 +1097,8 @@ Forwarded: Not-needed
  
  				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 @@
@@ -526,7 +1109,7 @@ Forwarded: Not-needed
  
  #include "i18n.h"
  
-@@ -196,7 +197,7 @@
+@@ -196,7 +197,7 @@ Editor::draw_measures ()
  	}
  
  	if (tempo_lines == 0) {
@@ -535,6 +1118,35 @@ Forwarded: Not-needed
  	}
  
  	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 @@
@@ -549,7 +1161,7 @@ Forwarded: Not-needed
  
  #ifdef __APPLE__
  #include <CoreAudio/CoreAudio.h>
-@@ -400,6 +402,8 @@
+@@ -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));
@@ -558,7 +1170,7 @@ Forwarded: Not-needed
  	}
  
  	if (unlock_memory_button.get_active()) {
-@@ -558,6 +562,17 @@
+@@ -558,6 +562,17 @@ EngineControl::build_command_line (vector<string>& cmd)
  bool
  EngineControl::engine_running ()
  {
@@ -576,9 +1188,25 @@ Forwarded: Not-needed
  	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 @@
+@@ -111,7 +111,6 @@ string
  ExportRangeMarkersDialog::get_target_filepath(string path, string filename, string postfix)
  {
  	string target_filepath = Glib::build_filename (path, filename + postfix);
@@ -586,6 +1214,36 @@ Forwarded: Not-needed
  	
  	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 @@
@@ -605,7 +1263,7 @@ Forwarded: Not-needed
  
  using namespace Gtk;
  using namespace ARDOUR;
-@@ -35,10 +40,14 @@
+@@ -35,10 +40,14 @@ LV2PluginUI::lv2_ui_write(LV2UI_Controller controller,
               uint32_t         format,
               const void*      buffer)
  {
@@ -622,7 +1280,7 @@ Forwarded: Not-needed
  		me->_lv2->set_parameter(port_index, *(float*)buffer);
    }
  }
-@@ -66,6 +75,8 @@
+@@ -66,6 +75,8 @@ LV2PluginUI::parameter_update (uint32_t port_index, float val)
  		return;
  	}
  
@@ -631,7 +1289,7 @@ Forwarded: Not-needed
  	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 @@
+@@ -120,6 +131,7 @@ LV2PluginUI::output_update()
  LV2PluginUI::LV2PluginUI (boost::shared_ptr<PluginInsert> pi, boost::shared_ptr<LV2Plugin> lv2p)
  	: PlugUIBase (pi)
  	, _lv2(lv2p)
@@ -639,9 +1297,11 @@ Forwarded: Not-needed
  	, _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 @@
+@@ -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;
@@ -658,6 +1318,8 @@ Forwarded: Not-needed
  	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 @@
@@ -677,7 +1339,7 @@ Forwarded: Not-needed
  
  #include <jack/jack.h>
  
-@@ -66,17 +69,18 @@
+@@ -66,17 +69,18 @@ static const char* localedir = LOCALEDIR;
  
  #include <mach-o/dyld.h>
  #include <sys/param.h>
@@ -698,7 +1360,7 @@ Forwarded: Not-needed
  	set_language_preference ();
  
  	char execpath[MAXPATHLEN+1];
-@@ -95,6 +99,15 @@
+@@ -95,6 +99,15 @@ fixup_bundle_environment ()
  	*/
  
  	path = dir_path;
@@ -714,7 +1376,7 @@ Forwarded: Not-needed
  	if (cstr) {
  		path += ':';
  		path += cstr;
-@@ -102,15 +115,17 @@
+@@ -102,15 +115,17 @@ fixup_bundle_environment ()
  	setenv ("PATH", path.c_str(), 1);
  
  	path = dir_path;
@@ -736,7 +1398,7 @@ Forwarded: Not-needed
  	path += "/../Resources/icons:";
  	path += dir_path;
  	path += "/../Resources/pixmaps:";
-@@ -163,23 +178,16 @@
+@@ -163,23 +178,16 @@ fixup_bundle_environment ()
  	
  	setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
  
@@ -765,7 +1427,7 @@ Forwarded: Not-needed
  	if (!ARDOUR::translations_are_disabled ()) {
  
  		path = dir_path;
-@@ -249,6 +257,152 @@
+@@ -249,6 +257,152 @@ fixup_bundle_environment ()
  	}
  }
  
@@ -918,7 +1580,7 @@ Forwarded: Not-needed
  #endif
  
  static gboolean
-@@ -312,10 +466,8 @@
+@@ -312,10 +466,8 @@ int main (int argc, char* argv[])
  #endif
  {
  	vector<Glib::ustring> null_file_list;
@@ -931,6 +1593,29 @@ Forwarded: Not-needed
  
          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 @@
@@ -942,6 +1627,8 @@ Forwarded: Not-needed
  "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 @@
@@ -953,6 +1640,8 @@ Forwarded: Not-needed
  "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 @@
@@ -964,6 +1653,8 @@ Forwarded: Not-needed
  "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 @@
@@ -974,6 +1665,8 @@ Forwarded: Not-needed
  "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 @@
@@ -985,6 +1678,8 @@ Forwarded: Not-needed
  "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 @@
@@ -995,6 +1690,8 @@ Forwarded: Not-needed
  "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 @@
@@ -1012,6 +1709,8 @@ Forwarded: Not-needed
  "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 @@
@@ -1023,6 +1722,8 @@ Forwarded: Not-needed
  "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 @@
@@ -1034,6 +1735,8 @@ Forwarded: Not-needed
  "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 @@
@@ -1045,6 +1748,8 @@ Forwarded: Not-needed
  "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 @@
@@ -1056,9 +1761,11 @@ Forwarded: Not-needed
  "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 @@
+@@ -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;
@@ -1066,19 +1773,49 @@ Forwarded: Not-needed
  	virtual void ensure_float (Gtk::Window&) = 0;
  	virtual void show_window () = 0;
  	virtual TrackViewList* get_valid_views (TimeAxisView*, ARDOUR::RouteGroup* grp = 0) = 0;
---- a/gtk2_ardour/SConscript
-+++ b/gtk2_ardour/SConscript
-@@ -291,6 +291,7 @@
- 	extra_sources += lv2_files
- 	gtkardour.Append (CCFLAGS="-DHAVE_LV2")
- 	gtkardour.Merge ([libraries['slv2']])
-+	gtkardour.Merge ([libraries['rasqal']])
+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;
+ }
  
- if gtkardour['GTKOSX']:
+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 @@
+@@ -979,6 +979,7 @@ SoundFileOmega::reset_options ()
  			}
  			if (same_size) {
  				channel_strings.push_back (_("all files in one track"));
@@ -1086,9 +1823,11 @@ Forwarded: Not-needed
  			}
  			
  		}
+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 @@
+@@ -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;
@@ -1097,9 +1836,11 @@ Forwarded: Not-needed
  	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 @@
+@@ -861,6 +861,7 @@ convert_color_channel (guint8 src,
  	return alpha ? ((guint (src) << 8) - src) / alpha : 0;
  }
  
@@ -1107,7 +1848,7 @@ Forwarded: Not-needed
  void
  convert_bgra_to_rgba (guint8 const* src,
  		      guint8*       dst,
-@@ -870,20 +871,42 @@
+@@ -870,20 +871,42 @@ convert_bgra_to_rgba (guint8 const* src,
  	guint8 const* src_pixel = src;
  	guint8*       dst_pixel = dst;
  	
@@ -1164,7 +1905,7 @@ Forwarded: Not-needed
  }
  
  Glib::RefPtr<Gdk::Pixbuf>
-@@ -917,3 +940,33 @@
+@@ -917,3 +940,33 @@ pixbuf_from_ustring(const ustring& name, Pango::FontDescription* font, uint32_t
  
  	return buf;
  }
@@ -1198,9 +1939,11 @@ Forwarded: Not-needed
 +                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 @@
+@@ -100,4 +100,7 @@ Glib::RefPtr<Gdk::Pixbuf> pixbuf_from_ustring (const Glib::ustring& name,
  					       int clip_width,
  					       int clip_height);
  
@@ -1208,9 +1951,147 @@ Forwarded: Not-needed
 +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 @@
+@@ -83,6 +83,7 @@ class AutomationList : public PBD::StatefulDestructible
  
  	void freeze();
  	void thaw ();
@@ -1218,6 +2099,17 @@ Forwarded: Not-needed
  
  	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 @@
@@ -1228,7 +2120,7 @@ Forwarded: Not-needed
  
  #include "ardour/utils.h"
  
-@@ -113,9 +114,9 @@
+@@ -113,9 +114,9 @@ class ConfigVariable : public ConfigVariableBase
  					if ((prop = child->property ("name")) != 0) {
  						if (prop->value() == _name) {
  							if ((prop = child->property ("value")) != 0) {
@@ -1241,7 +2133,7 @@ Forwarded: Not-needed
  								_owner = (ConfigVariableBase::Owner)(_owner |owner);
  								return true;
  							}
-@@ -138,12 +139,12 @@
+@@ -138,12 +139,12 @@ class ConfigVariable : public ConfigVariableBase
  			for (oiter = olist.begin(); oiter != olist.end(); ++oiter) {
  				
  				option = *oiter;
@@ -1258,6 +2150,521 @@ Forwarded: Not-needed
  						_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 @@
@@ -1273,7 +2680,7 @@ Forwarded: Not-needed
  
  #include <ardour/audioengine.h>
  #include <ardour/buffer.h>
-@@ -332,7 +335,10 @@
+@@ -332,7 +335,10 @@ AudioEngine::process_callback (nframes_t nframes)
  
  	IO::CycleStart (nframes);
  
@@ -1285,7 +2692,7 @@ Forwarded: Not-needed
  		if (Freewheel (nframes)) {
  			jack_set_freewheel (_priv_jack, false);
  		}
-@@ -667,7 +673,7 @@
+@@ -667,7 +673,7 @@ int
  AudioEngine::connect (const string& source, const string& destination)
  {
          GET_PRIVATE_JACK_POINTER_RET (_jack, -1);
@@ -1294,7 +2701,7 @@ Forwarded: Not-needed
  	string s = make_port_name_non_relative (source);
  	string d = make_port_name_non_relative (destination);
  
-@@ -1116,10 +1122,20 @@
+@@ -1116,10 +1122,20 @@ AudioEngine::remove_connections_for (Port* port)
  int
  AudioEngine::connect_to_jack (string client_name)
  {
@@ -1315,7 +2722,7 @@ Forwarded: Not-needed
  	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 @@
+@@ -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;
  		}
@@ -1324,9 +2731,89 @@ Forwarded: Not-needed
  		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 @@
+@@ -735,7 +735,7 @@ AudioRegion::state (bool full)
  			child->add_child_nocopy (_fade_in.get_state ());
  		}
  
@@ -1335,7 +2822,7 @@ Forwarded: Not-needed
  		
  		child = node.add_child (X_("FadeOut"));
  		
-@@ -745,7 +745,7 @@
+@@ -745,7 +745,7 @@ AudioRegion::state (bool full)
  			child->add_child_nocopy (_fade_out.get_state ());
  		}
  		
@@ -1344,62 +2831,273 @@ Forwarded: Not-needed
  	}
  	
  	child = node.add_child ("Envelope");
---- a/libs/ardour/audio_unit.cc
-+++ b/libs/ardour/audio_unit.cc
-@@ -446,17 +446,26 @@
- 		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);
+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)
+ }
  
--	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();
-+                }
-+        }
+ void
+-AutomationList::stop_touch (bool mark, double when)
++AutomationList::stop_touch (bool mark, double when, double value)
+ {
+ 	g_atomic_int_set (&_touching, 0);
  
- 	/* tell the plugin about tempo/meter/transport callbacks in case it wants them */
+@@ -268,6 +268,11 @@ AutomationList::stop_touch (bool mark, double when)
+                         delete ninfo;
+                 }
+         }
++        
++	//if no automation yet
++    if (events.empty()) {
++		default_value = value;
++	}
+ }
  
-@@ -475,13 +484,6 @@
- 			   &info,
- 			   sizeof (HostCallbackInfo));
+ 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);
+ }
  
--	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);
+ 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 */
 -
- 	/* these keep track of *configured* channel set up,
- 	   not potential set ups.
- 	*/
+-                                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 @@
+@@ -711,10 +711,13 @@ Crossfade::set_state (const XMLNode& node)
  	nframes_t val;
  
  	if ((prop = node.property ("position")) != 0) {
@@ -1417,7 +3115,7 @@ Forwarded: Not-needed
  		}
  	} else {
  		warning << _("old-style crossfade information - no position information") << endmsg;
-@@ -751,12 +754,14 @@
+@@ -751,12 +754,14 @@ Crossfade::set_state (const XMLNode& node)
  
  	if ((prop = node.property ("length")) != 0) {
  
@@ -1437,7 +3135,7 @@ Forwarded: Not-needed
  	} else {
  		
  		/* XXX this branch is legacy code from before
-@@ -798,6 +803,11 @@
+@@ -798,6 +803,11 @@ Crossfade::set_state (const XMLNode& node)
  		}
  	}
  
@@ -1449,7 +3147,7 @@ Forwarded: Not-needed
  	_fade_in.front()->value=0.0;
  	_fade_in.back()->value=1.0;
  
-@@ -826,6 +836,11 @@
+@@ -826,6 +836,11 @@ Crossfade::set_state (const XMLNode& node)
  		}
  	}
  
@@ -1461,9 +3159,11 @@ Forwarded: Not-needed
  	_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 @@
+@@ -312,7 +312,7 @@ Curve::_get_vector (double x0, double x1, float *vec, int64_t veclen)
  		return;
  	}
  
@@ -1472,7 +3172,7 @@ Forwarded: Not-needed
   	
   		for (i = 0; i < veclen; ++i) {
   			vec[i] = events.front()->value;
-@@ -355,17 +355,18 @@
+@@ -355,17 +355,18 @@ Curve::_get_vector (double x0, double x1, float *vec, int64_t veclen)
  
  	rx = lx;
  
@@ -1500,9 +3200,21 @@ Forwarded: Not-needed
  	}
  }
  
+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
-@@ -147,6 +147,7 @@
+@@ -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);	
@@ -1510,6 +3222,45 @@ Forwarded: Not-needed
  	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 @@
@@ -1521,6 +3272,8 @@ Forwarded: Not-needed
  "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 @@
@@ -1532,6 +3285,8 @@ Forwarded: Not-needed
  "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 @@
@@ -1543,6 +3298,8 @@ Forwarded: Not-needed
  "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 @@
@@ -1554,6 +3311,8 @@ Forwarded: Not-needed
  "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 @@
@@ -1565,6 +3324,8 @@ Forwarded: Not-needed
  "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 @@
@@ -1576,6 +3337,8 @@ Forwarded: Not-needed
  "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 @@
@@ -1587,6 +3350,8 @@ Forwarded: Not-needed
  "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 @@
@@ -1598,19 +3363,43 @@ Forwarded: Not-needed
  "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"
---- a/libs/ardour/SConscript
-+++ b/libs/ardour/SConscript
-@@ -320,6 +320,7 @@
- 	
- if ardour['LV2']:
- 	ardour.Merge ([ libraries['slv2'] ])
-+	ardour.Merge ([ libraries['rasqal'] ])
+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;
+ }
  
- if ardour['LIBLO']:
- 	ardour.Merge ([ libraries['lo'] ])
+-	
++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 @@
+@@ -2631,7 +2631,7 @@ Session::find_current_end ()
  
  	nframes_t max = get_maximum_extent ();
  
@@ -1619,9 +3408,31 @@ Forwarded: Not-needed
  		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 @@
+@@ -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);
@@ -1629,9 +3440,33 @@ Forwarded: Not-needed
  			}
  		}
  		
+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 @@
+@@ -299,7 +299,21 @@ TempoMap::move_metric_section (MetricSection& section, const BBT_Time& when)
  void
  TempoMap::move_tempo (TempoSection& tempo, const BBT_Time& when)
  {
@@ -1654,7 +3489,7 @@ Forwarded: Not-needed
  		StateChanged (Change (0));
  	}
  }
-@@ -307,7 +321,21 @@
+@@ -307,7 +321,21 @@ TempoMap::move_tempo (TempoSection& tempo, const BBT_Time& when)
  void
  TempoMap::move_meter (MeterSection& meter, const BBT_Time& when)
  {
@@ -1677,9 +3512,11 @@ Forwarded: Not-needed
  		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 @@
+@@ -146,7 +146,6 @@ BarController::entry_output ()
  	
  	stringstream stream;
  	string str;
@@ -1687,9 +3524,23 @@ Forwarded: Not-needed
  
  	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 @@
+@@ -51,6 +51,7 @@ namespace Gtkmm2ext {
  
  class TextViewer;
  
@@ -1697,7 +3548,7 @@ Forwarded: Not-needed
  extern BaseUI::RequestType ErrorMessage;
  extern BaseUI::RequestType Quit;
  extern BaseUI::RequestType CallSlot;
-@@ -77,6 +78,10 @@
+@@ -77,6 +78,10 @@ struct UIRequest : public BaseUI::BaseRequestObject {
      void *arg;
      const char *msg2;
      sigc::slot<void> slot;
@@ -1708,19 +3559,37 @@ Forwarded: Not-needed
      
      ~UIRequest () { 
  	    if (type == ErrorMessage && msg) {
---- a/libs/gtkmm2ext/gtk_ui.cc
-+++ b/libs/gtkmm2ext/gtk_ui.cc
-@@ -52,6 +52,7 @@
- pthread_t UI::gui_thread;
- UI       *UI::theGtkUI = 0;
+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>
  
-+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();
+ #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 @@
+@@ -174,6 +174,98 @@ EnumWriter::write_distinct (EnumRegistration& er, int value)
  	return string();
  }
  
@@ -1819,7 +3688,7 @@ Forwarded: Not-needed
  int
  EnumWriter::read_bits (EnumRegistration& er, string str)
  {
-@@ -186,14 +278,16 @@
+@@ -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') {
@@ -1839,7 +3708,7 @@ Forwarded: Not-needed
  
  	do {
  		
-@@ -231,14 +325,16 @@
+@@ -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') {
@@ -1859,6 +3728,9 @@ Forwarded: Not-needed
  
  	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 @@
@@ -1992,6 +3864,22 @@ Forwarded: Not-needed
 +                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 @@
@@ -2024,20 +3912,20 @@ Forwarded: Not-needed
  		cerr << _("cannot create thread request buffer key") << endl;
  		throw failed_constructor();
  	}
-@@ -30,10 +42,24 @@
+@@ -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;
@@ -2051,7 +3939,7 @@ Forwarded: Not-needed
  		request_buffers[thread_id] = b;
  	}
  
-@@ -93,33 +119,42 @@
+@@ -93,33 +119,42 @@ AbstractUI<RequestObject>::handle_ui_requests ()
  
  	request_buffer_map_lock.lock ();
  
@@ -2118,9 +4006,11 @@ Forwarded: Not-needed
  	}
  
  	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 @@
+@@ -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);
  
@@ -2144,6 +4034,8 @@ Forwarded: Not-needed
  	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 @@
@@ -2156,7 +4048,7 @@ Forwarded: Not-needed
  #include <map>
  #include <string>
  #include <vector>
-@@ -45,6 +48,7 @@
+@@ -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);
@@ -2164,7 +4056,7 @@ Forwarded: Not-needed
  
    private:
  	struct EnumRegistration {
-@@ -68,10 +72,16 @@
+@@ -68,10 +72,16 @@ class EnumWriter {
  
  	static EnumWriter* _instance;
  	static std::map<std::string,std::string> hack_table;
@@ -2181,6 +4073,9 @@ Forwarded: Not-needed
  #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 @@
@@ -2233,19 +4128,11 @@ Forwarded: Not-needed
 +}
 +
 +#endif /* __libpbd_epa_h__ */
---- a/libs/pbd/SConscript
-+++ b/libs/pbd/SConscript
-@@ -26,6 +26,7 @@
- controllable.cc
- enumwriter.cc
- dmalloc.cc
-+epa.cc
- error.cc
- fpu.cc
- id.cc
+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 @@
+@@ -40,6 +40,8 @@ UndoTransaction::UndoTransaction (const UndoTransaction& rhs)
  {
  	_name = rhs._name;
  	_clearing = false;
@@ -2254,9 +4141,43 @@ Forwarded: Not-needed
  	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
-@@ -622,9 +622,15 @@
+@@ -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
@@ -2274,9 +4195,11 @@ Forwarded: Not-needed
  	}
  	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 @@
+@@ -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);
@@ -2289,63 +4212,194 @@ Forwarded: Not-needed
  				state.delta = float( state.ticks ) / float( 0x3f );
  				
  				/*
---- a/SConstruct
-+++ b/SConstruct
-@@ -545,6 +545,14 @@
- 	else:
- 		print 'LV2 support is not enabled (SLV2 not found or older than 0.6.0)'
- 		env['LV2'] = 0
+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:
 +
-+	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
++On most distributions, you can double-click the file "install.sh".
 +
- 	conf.Finish()
- else:
- 	print 'LV2 support is not enabled.  Build with \'scons LV2=1\' to enable.'
-@@ -1027,6 +1035,9 @@
-     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()
++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.
 +
- env = conf.Finish()
- 
- if env['GTKOSX']:
-@@ -1226,6 +1237,15 @@
- if env['RUBBERBAND']:
-     timefx_subdirs += ['libs/rubberband']
- 
-+#
-+# Tools
-+#
-+if env['IS_OSX'] == 0 :
-+	tools_subdirs = [ 'tools/sanity_check' ]
-+else:
-+	tools_subdirs = [ ]
 +
++* Links and Menu entries:
 +
- opts.Save('scache.conf', env)
- Help(opts.GenerateHelpText(env))
- 
-@@ -1403,7 +1423,7 @@
- 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')
- 
++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,40 @@
+@@ -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}
 +
@@ -2380,13 +4434,21 @@ Forwarded: Not-needed
 +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
 +
-+exec $INSTALL_DIR/bin/ardour-%VER% "$@"
++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,619 @@
+@@ -0,0 +1,660 @@
 +#!/bin/bash
 +
 +#
@@ -2404,11 +4466,12 @@ Forwarded: Not-needed
 +MIXBUS=
 +INTERNAL_JACK=1
 +WITH_LADSPA=0
-+STRIP=1
++STRIP=all
 +PRINT_SYSDEPS=
 +WITH_NLS=
 +EXTERNAL_JACK=
 +VENDOR=Ardour ;
++BUILDTYPE=""
 +
 +if [ $# -eq 0 ] ; then
 +	echo ""	 
@@ -2432,7 +4495,7 @@ Forwarded: Not-needed
 +		SAE=1 ; 
 +		INTERNAL_JACK=1; 
 +		WITH_LADSPA=1; 
-+		STRIP=1; 
++		STRIP=all; 
 +		APPNAME=Ardour ;
 +		shift ;;
 +	--mixbus)
@@ -2441,7 +4504,7 @@ Forwarded: Not-needed
 +		SAE= ; 
 +		INTERNAL_JACK=; 
 +		WITH_LADSPA=; 
-+		STRIP=1; 
++		STRIP=all;
 +		APPNAME=Mixbus ;
 +		VENDOR=Harrison ;
 +		shift ;;
@@ -2450,7 +4513,7 @@ Forwarded: Not-needed
 +		SAE= ; 
 +		INTERNAL_JACK=; 
 +		WITH_LADSPA=; 
-+		STRIP=1; 
++		STRIP=all ; 
 +		APPNAME=Ardour ;
 +		shift ;;
 +	--allinone)
@@ -2458,9 +4521,9 @@ Forwarded: Not-needed
 +		WITH_NLS= ; 
 +		INTERNAL_JACK=1; 
 +		WITH_LADSPA=1; 
-+		STRIP=1; 
++		STRIP=all; 
 +		shift ;;
-+	--test) SAE= ; INTERNAL_JACK=; WITH_LADSPA=; STRIP= ; shift ;;
++	--test) SAE= ; INTERNAL_JACK=; WITH_LADSPA=; STRIP=all ; shift ;;
 +
 +	#
 +	# specific build flags
@@ -2468,7 +4531,7 @@ Forwarded: Not-needed
 +
 +	--nojack) INTERNAL_JACK= ; shift ;;
 +	--noladspa) WITH_LADSPA= ; shift ;;
-+	--nostrip) STRIP= ; shift ;;
++	--strip) STRIP=$2 ; shift ; shift ;;
 +	--sysdeps) PRINT_SYSDEPS=1; shift ;;
 +	--nls) WITH_NLS=1 ; shift ;;
 +	--external_jack) EXTERNAL_JACK=$2; shift ; shift ;;
@@ -2483,6 +4546,12 @@ Forwarded: Not-needed
 +	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
@@ -2513,9 +4582,32 @@ Forwarded: Not-needed
 +		;;
 +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
 +
-+APPDIR=${APPNAME}_${ARCH}-${release_version}_${svn_version}
++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
@@ -2602,7 +4694,7 @@ Forwarded: Not-needed
 +
 +echo "Copying ardour executable ...."
 +cp ../../gtk2_ardour/$MAIN_EXECUTABLE $APPBIN
-+if test x$STRIP != x ; then
++if test x$STRIP = xall ; then
 +	strip $APPBIN/$MAIN_EXECUTABLE
 +fi
 +
@@ -2828,6 +4920,7 @@ Forwarded: Not-needed
 +echo $OURLIBS${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}
 +
 +checkedIdx=0
++deplibs=
 +
 +while [ true ] ; do 
 +	missing=false
@@ -2888,6 +4981,10 @@ Forwarded: Not-needed
 +					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
@@ -2900,11 +4997,15 @@ Forwarded: Not-needed
 +echo
 +
 +# strip libraries
-+if test x$STRIP != x ; then
-+	echo Stripping libraries
-+	find $APPLIB/ -name "*.so*" | xargs strip
++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  ..."
@@ -2985,8 +5086,7 @@ Forwarded: Not-needed
 +#
 +# Add the uninstaller
 +#
-+APP_VER_NAME=${APPNAME}-${release_version}_${svn_version}
-+sed -e "s/%REPLACE_PGM%/${APPNAME}/" -e "s/%REPLACE_VENDOR%/${VENDOR}/" -e "s/%REPLACE_VERSION%/${release_version}/" -e "s/%REPLACE_BUILD%/${svn_version}/" < uninstall.sh.in > $APPBIN/${APP_VER_NAME}.uninstall.sh
++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
@@ -3002,10 +5102,16 @@ Forwarded: Not-needed
 +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 @@
@@ -3017,6 +5123,9 @@ Forwarded: Not-needed
 +   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 @@
@@ -3045,9 +5154,12 @@ Forwarded: Not-needed
 +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,90 @@
+@@ -0,0 +1,176 @@
 +#!/bin/bash
 +
 +# package
@@ -3055,6 +5167,11 @@ Forwarded: Not-needed
 +# 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 ""	 
@@ -3083,6 +5200,8 @@ Forwarded: Not-needed
 +		APPNAME=Ardour ;
 +		shift ;;
 +
++	--singlearch) SINGLE_ARCH="T" ; shift ;;
++
 +	*)
 +		#catch all for unknown arguments
 +		echo ""
@@ -3094,27 +5213,97 @@ Forwarded: Not-needed
 +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_BUILD="${APPNAME}_x86-${release_version}_${svn_version}.tar.bz2"
-+X86_64_BUILD="${APPNAME}_x86_64-${release_version}_${svn_version}.tar.bz2"
-+PACKAGE="${APPNAME}-${release_version}_${svn_version}"
++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_BUILD} ]; then
++
++if [ ! -e ${X86_BUNDLE}.tar.bz2 ] ; then
 +	echo ""
-+	echo "!!! ERROR !!! - Can't locate x86 build file ${X86_BUILD}"
++	echo "Can't locate x86 bundle file ${X86_BUNDLE}.tar.bz2"
 +	echo ""
-+	exit 1
++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_BUILD} ]; then
++if [ ! -e ${X86_64_BUNDLE}.tar.bz2 ]; then
 +	echo ""
-+	echo "!!! ERROR !!! - Can't locate x86_64 build file ${X86_64_BUILD}"
++	echo "Can't locate x86_64 bundle file ${X86_64_BUNDLE}.tar.bz2"
 +	echo ""
-+	exit 1
++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
@@ -3123,14 +5312,23 @@ Forwarded: Not-needed
 +
 +echo "Creating new package dir..."
 +mkdir ${PACKAGE}
-+mv ${X86_BUILD} ${PACKAGE}
-+mv ${X86_64_BUILD} ${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 -czf ${PACKAGE}.tar.gz ${PACKAGE}
++tar -cf ${PACKAGE}.tar ${PACKAGE}
 +
 +echo "Clean up"
 +rm -rf ${PACKAGE}
@@ -3138,47 +5336,12 @@ Forwarded: Not-needed
 +echo ""
 +echo "Done"
 +echo ""
---- /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/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,525 @@
+@@ -0,0 +1,621 @@
 +#!/bin/sh
 +
 +####################################
@@ -3240,7 +5403,7 @@ Forwarded: Not-needed
 +
 +	if which yum > /dev/null;
 +	then
-+		sudo yum -y install $1
++		${SUPER} yum -y install $1
 +		rtrn=$?
 +
 +		if [ $rtrn -ne 0 ];
@@ -3253,7 +5416,7 @@ Forwarded: Not-needed
 +
 +	elif which apt-get > /dev/null;
 +	then
-+		sudo apt-get -y install $1
++		${SUPER} apt-get -y install $1
 +		rtrn=$?
 +
 +		if [ $rtrn -ne 0 ];
@@ -3289,20 +5452,53 @@ Forwarded: Not-needed
 +echo "Welcome to the ${PGM_NAME} installer"
 +echo ""
 +
-+##############
-+# Check sudo
-+##############
++#############################
++# Check for root privileges
++#############################
 +
-+if ! sudo date;
-+then
++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 "!!! ERROR !!!"
++	echo "!!! Warning !!!"
 +	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 (hint: use visudo to edit sudoers file)"
++	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 exit installer:" BLAH
-+	exit 1
++	read -p "Press ENTER to continue:" BLAH
++	
 +fi
 +
 +############################
@@ -3327,8 +5523,57 @@ Forwarded: Not-needed
 +		;;
 +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}-*"`)
 +
@@ -3400,11 +5645,20 @@ Forwarded: Not-needed
 +################################
 +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_FULL_NAME="${PGM_NAME}-${PGM_VERSION}_${PGM_BUILD}"
++PGM_BUILDTYPE=$(echo ${BUNDLE_DIR} | awk 'BEGIN { FS = "-" } ; { print $3 }')
 +
-+ICON_NAME="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}"			#no dash since it seperates vendor from program
-+MENU_FILE="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}.desktop"	#no dash since it seperates vendor from program
-+DESKTOP_LINK_FILE="${PGM_NAME}_${PGM_VERSION}.desktop"
++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"
@@ -3442,7 +5696,7 @@ Forwarded: Not-needed
 +			echo "Running uninstaller $i"
 +			
 +			${i}
-+			sudo rm -f ${i}
++			${SUPER} rm -f ${i}
 +		fi
 +	done
 +fi
@@ -3455,8 +5709,8 @@ Forwarded: Not-needed
 +echo ""
 +
 +# Copy the new version in the install directory
-+sudo mkdir ${INSTALL_DEST_BASE}/${PGM_FULL_NAME} 
-+sudo cp -Rf	${BUNDLE_DIR}/* ${INSTALL_DEST_BASE}/${PGM_FULL_NAME}/
++${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}
@@ -3465,30 +5719,35 @@ Forwarded: Not-needed
 +echo "Type=Application" >> /tmp/${MENU_FILE}
 +echo "Terminal=false" >> /tmp/${MENU_FILE}
 +echo "Exec=${PGM_EXEC_PATH}" >> /tmp/${MENU_FILE}
-+echo "Name=${PGM_NAME}-${PGM_VERSION}" >> /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}
-+sudo mv /tmp/${MENU_FILE} ${MENU_FILE_PATH}/.
++${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"
-+	sudo xdg-icon-resource install --context apps --size 16 ${ICON_PATH}/${PGM_NAME_LOWER}_icon_16px.png ${ICON_NAME}
-+	sudo xdg-icon-resource install --context apps --size 22 ${ICON_PATH}/${PGM_NAME_LOWER}_icon_22px.png ${ICON_NAME}
-+	sudo xdg-icon-resource install --context apps --size 32 ${ICON_PATH}/${PGM_NAME_LOWER}_icon_32px.png ${ICON_NAME}
-+	sudo xdg-icon-resource install --context apps --size 48 ${ICON_PATH}/${PGM_NAME_LOWER}_icon_48px.png ${ICON_NAME}
++	${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
-+		sudo cp -f ${ICON_PATH}/${PGM_NAME_LOWER}_icon.svg  /usr/share/icons/hicolor/scalable/apps/${ICON_NAME}.svg
++		${SUPER} cp -f ${ICON_PATH}/${PGM_NAME_LOWER}_icon.svg  /usr/share/icons/hicolor/scalable/apps/${ICON_NAME}.svg
 +	fi
 +
-+	sudo xdg-desktop-menu install ${MENU_FILE_PATH}/${MENU_FILE}
-+	sudo xdg-desktop-menu forceupdate --mode system			# Some systems need an extra kick
++	${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}"
@@ -3505,7 +5764,7 @@ Forwarded: Not-needed
 +echo "Copying uninstall script to ${INSTALL_DEST_BASE}"
 +echo ""
 +
-+sudo cp -f ${BUNDLE_DIR}/bin/*.uninstall.sh ${INSTALL_DEST_BASE}/.
++${SUPER} cp -f ${BUNDLE_DIR}/bin/*.uninstall.sh ${INSTALL_DEST_BASE}/.
 +
 +###########################
 +# Check Jack and qjackctl
@@ -3607,7 +5866,7 @@ Forwarded: Not-needed
 +					read -p "Press ENTER to continue:" BLAH
 +
 +					user=`whoami`
-+					if sudo usermod -a -G audio $user;
++					if ${SUPER} usermod -a -G audio $user;
 +					then
 +						USER_GROUP_ADJUSTED="t"
 +					else
@@ -3629,7 +5888,7 @@ Forwarded: Not-needed
 +					read -p "Press ENTER to continue:" BLAH
 +
 +					user=`whoami`
-+					if sudo usermod -a -G jackuser $user;
++					if ${SUPER} usermod -a -G jackuser $user;
 +					then
 +						USER_GROUP_ADJUSTED="t"
 +					else
@@ -3704,9 +5963,12 @@ Forwarded: Not-needed
 +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,84 @@
+@@ -0,0 +1,130 @@
 +#!/bin/sh
 +
 +######################################
@@ -3721,19 +5983,65 @@ Forwarded: Not-needed
 +PGM_VENDOR="%REPLACE_VENDOR%"
 +PGM_VERSION="%REPLACE_VERSION%"
 +PGM_BUILD="%REPLACE_BUILD%"
++PGM_BUILDTYPE="%REPLACE_TYPE%"
 +
 +INSTALL_DEST_BASE=/opt
 +
 +
 +#### Derived Variables ####
-+PGM_PATH=${INSTALL_DEST_BASE}/${PGM_NAME}-${PGM_VERSION}_${PGM_BUILD}
++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
 +
-+ICON_NAME="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}"			#no dash between name and version since seperates vendor from program
-+MENU_FILE="${PGM_VENDOR}-${PGM_NAME}_${PGM_VERSION}.desktop"	#no dash between name and version since seperates vendor from program
-+DESKTOP_LINK_FILE="${PGM_NAME}_${PGM_VERSION}.desktop"
 +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
 +#######################
@@ -3766,31 +6074,52 @@ Forwarded: Not-needed
 +
 +	if [ "T" = ${HAS_XDG} ];
 +	then
-+		sudo xdg-desktop-menu uninstall ${MENU_FILE_PATH}
-+		sudo xdg-icon-resource uninstall --size 16 ${ICON_NAME}
-+		sudo xdg-icon-resource uninstall --size 22 ${ICON_NAME}
-+		sudo xdg-icon-resource uninstall --size 32 ${ICON_NAME}
-+		sudo xdg-icon-resource uninstall --size 48 ${ICON_NAME}
++		${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
-+			sudo rm -f /usr/share/icons/hicolor/scalable/apps/${ICON_NAME}.svg
++			${SUPER} rm -f /usr/share/icons/hicolor/scalable/apps/${ICON_NAME}.svg
 +		fi
 +	fi
 +
 +	if [ -e ~/Desktop/${DESKTOP_LINK_FILE} ];
 +	then
-+		sudo rm -f ~/Desktop/${DESKTOP_LINK_FILE}
++		${SUPER} rm -f ~/Desktop/${DESKTOP_LINK_FILE}
 +	fi
 +
 +	# delete the old package
-+	sudo rm -rf ${PGM_PATH}
-+	sudo rm -f $0
++	${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 @@
@@ -4153,21 +6482,9 @@ Forwarded: Not-needed
 +
 +	return status;
 +}
---- /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/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 @@
@@ -4504,6 +6821,9 @@ Forwarded: Not-needed
 +
 +  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 @@

-- 
ardour Debian packaging



More information about the pkg-multimedia-commits mailing list